を呼び出すThread.sleep
ことで、ペイント要求の処理などを担当するイベント ディスパッチ スレッドをブロックする可能性があります。これは、ループが実際に終了するまで、EDT がパネルの更新された場所を処理できないことを意味します。
代わりに、javax.swing.Timer
...
詳細については、Swing の同時実行を確認してください。
更新しました
これはところでFlowLayoutの下にあるので、何か関係があるかもしれないと思いますが、よくわかりません
revalidate
レイアウト マネージャーと戦っている場合、使用しているコンテナーusePanel
が配置されると、レイアウト マネージャーがコンポーネントを配置したい場所に再配置されることがわかります。
より良い解決策については、Sliding-Layoutをご覧ください。
基本的な例で更新
アニメーションは、時間の経過に伴う変化の錯覚です。Swing では、UI の更新に関して、開発者にかなり厳しい要件を課しています。
レイアウト マネージャーなどとは別に、Swing では、UI に対するすべての対話と変更を、イベント ディスパッチ スレッドのコンテキスト内で行う必要があります。また、長時間実行またはブロック プロセスは、EDT 以外の別のスレッドで実行する必要があります。
これにより、キャッチ 22 に置かれます。バックグラウンドで実行する必要があるため、EDT によるペイント リクエストの処理を (とりわけ) 停止することはありませんが、EDT のコンテキスト内からコンポーネントを更新する必要があります...
幸いなことに、利用可能なソリューションは多数あります。あなたの問題に対する最も簡単な方法は、javax.swing.Timer
この例では、ルート ペインのグラス ペイン機能を使用して、上にスライド アウトを提供します。詳細については、ルート ペインの使用方法を参照してください。
また、可変タイミング アニメーションを使用します。つまり、パネルの位置は、一定のデルタではなく、アニメーションの時間の進行に基づいています。
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class SlidingPane {
private SlidePane slidePane = new SlidePane();
public static void main(String[] args) {
new SlidingPane();
}
public SlidingPane() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JButton slideButton = new JButton("Slide");
slideButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
slidePane.slide();
}
});
JFrame frame = new JFrame("Testing");
JPanel glassPane = new JPanel(null);
glassPane.setOpaque(false);
glassPane.add(slidePane);
frame.setGlassPane(glassPane);
glassPane.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(new JLabel("Look ma, no hands!"), gbc);
frame.add(slideButton, gbc);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SlidePane extends JPanel {
private long startTime = -1;
private int runTime = 1000;
private int startX;
private int targetX;
private boolean slideIn = false;
private Timer slideTimer;
public SlidePane() {
setBackground(Color.DARK_GRAY);
setBorder(new LineBorder(Color.BLACK));
setLocation(-getPreferredSize().width, 0);
setLayout(new GridBagLayout());
JLabel label = new JLabel("I'm your overload");
label.setForeground(Color.WHITE);
add(label);
slideTimer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long diff = System.currentTimeMillis() - startTime;
double progress = (double)diff / (double)runTime;
if (progress >= 1d) {
progress = 1d;
slideTimer.stop();
startTime = -1;
}
Container parent = getParent();
int height = parent.getHeight();
setSize(getPreferredSize().width, height);
int x = calculateProgress(startX, targetX, progress);
setLocation(x, 0);
revalidate();
repaint();
}
});
}
protected int calculateProgress(int startValue, int endValue, double fraction) {
int value = 0;
int distance = endValue - startValue;
value = (int) Math.round((double) distance * fraction);
value += startValue;
return value;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 400);
}
public void slide() {
slideTimer.stop();
startTime = System.currentTimeMillis();
slideIn = !slideIn;
startX = getX();
targetX = 0;
if (!slideIn) {
targetX = -getPreferredSize().width;
}
slideTimer.start();
}
}
}