我是Java swing编程的新手。我想制作一个框架,它将依次呈现红色和蓝色。所以,我带了2个孩子JPanel,1个用于红色,其他用于蓝色,还有一个for循环。在每次迭代中,我从父面板中删除一个面板并添加另一个面板。但是,当我运行程序时,它只显示帧的最后一个状态。
任何人都可以解释原因吗?以及使程序像这样工作的预期方法是什么? 我的代码:
public class Test2 extends JFrame {
public Test2() {
JPanel Red = new JPanel(new BorderLayout());
JPanel Blue = new JPanel(new BorderLayout());
//...initialize Red and Blue
Red.setBackground(Color.red);
Blue.setBackground(Color.blue);
Red.setPreferredSize(new Dimension(200,200));
Blue.setPreferredSize(new Dimension(200,200));
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(200,200));
add(panel);
pack();
setTitle("Border Example");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
int M = 1000000; //note that, I made a long iteration to not finish the program fast and visualize the effect
for(int i=0;i<M;i++)
{
if(i%(M/10)==0) System.out.println(i); //to detect whether the program is running
if(i%2==0)
{
panel.removeAll();
panel.repaint();
panel.revalidate();
panel.add(Red,BorderLayout.CENTER);
}
else
{
panel.removeAll();
panel.repaint();
panel.revalidate();
panel.add(Blue,BorderLayout.CENTER);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test2 ex = new Test2();
ex.setVisible(true);
}
});
}}
答案 0 :(得分:2)
不要使用循环。 Swing只会在整个循环执行完毕后重新绘制框架。
相反,您需要使用Swing Timer。当Timer触发时,您调用逻辑。阅读How to Use Swing Timers上的Swing教程中的部分。
以下是一个简单的计时器示例,它只显示每秒的时间:Update a Label with a Swing Timer
此外,请勿删除/添加面板。相反,您可以使用Card Layout
并摇动可见面板。再次阅读How to Use CardLayout上的教程。
答案 1 :(得分:2)
基本上你不需要使用while
(或任何其他)循环,Swing只有在完成该循环后才会进行绘制,然后重新绘制GUI。
如前所述@camickr对他的回答,你可以试试Swing Timer
;这里的example完全符合您的要求。
根据您对其他答案的评论:
你能解释一下为什么&#34;重拍&#34;在循环中不起作用?为什么Timer没有&#34;重绘&#34;?
Swing很聪明,知道它不需要在循环中重新绘制,而是一旦循环结束它就会重新绘制,如果你在第3步中阅读Swing Custom Paint上的教程,它会说:
&#34; Swing非常聪明,可以在一次绘画操作中获取该信息并重新绘制屏幕的这些部分。换句话说,Swing不会连续两次重新绘制该组件,即使这是代码似乎正在执行的操作。&#34;
计时器将重新绘制它,因为它没有在EDT上运行但是在它自己的线程中
答案 2 :(得分:0)
我建议一次采取一步。
首先让它在不改变面板/颜色的情况下运行。
现在不是因为这个
public final void Test2() {
是一个方法(从未使用过)而不是构造函数。 更改为构造函数声明,如:
public Test2() {
让程序做点什么。然后你可以进入下一步。
还使用Java命名约定(如蓝色而不是蓝色)。