java - 多次更改JPanel的背景颜色
问题描述
我正在尝试制作一个小程序,其中包括基于时间更改面板的颜色。现在我只是试着做那部分而没有其他的。所以我只写了一个只有一个面板的小界面,我想在一个循环内多次更改颜色。问题是,即使线程暂停了正确的时间,面板的颜色也不会正确改变。它只是有时在循环中改变,而不是每次都改变。
我的接口类:
import javax.swing.*;
import java.awt.*;
//creates the Interface
public class Interface extends JFrame {
private JPanel frame1;
public Interface (String titel) {
super(titel);
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame1 = new JPanel();
this.frame1.setPreferredSize(new Dimension (200, 200));
setLayout(new FlowLayout());
add(frame1);
this.setVisible(true);
}
public JPanel getFrame1() {
return frame1;
}
}
我的暂停课:
import java.util.TimerTask;
//supposed to pause the thread by @pause amount of milliseconds
public class Pause extends TimerTask {
private int pause;
public Pause(int pause){
this.pause = pause;
}
@Override
public void run() {
System.out.println("Timer"+ pause+" task started at:"+System.currentTimeMillis());
pause();
System.out.println("Timer task"+ pause+" ended at:"+System.currentTimeMillis());
}
public void pause() {
try {
Thread.sleep(this.pause);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我的眨眼班
import javax.swing.*;
import java.awt.*;
public class Blink {
private JPanel frame1;
public Blink(Interface anInterface){
this.frame1 = anInterface.getFrame1();
}
// blink should change the color of the JPanel inside my Frame.
// Its supposed to change to red for 200 ms
// and then to white again for 1000 ms.
// this should be repeated 10 times.
public void blink() {
Pause pause1 = new Pause(200);
Pause pause2 = new Pause(1000);
pause2.run();
int i = 1;
while(i <= 10){
i++;
frame1.setBackground(Color.red);
frame1.repaint();
pause1.run();
frame1.setBackground(Color.white);
frame1.repaint();
pause2.run();
}
}
public static void main ( String[] args ) {
Interface anInterface = new Interface("Title");
anInterface.setVisible(true);
Blink blink = new Blink(anInterface);
blink.blink();
}
}
解决方案
根据Concurrency to Swing,您不能简单地Thread.sleep
确定Thread
GUI 的运行位置,因为它会冻结它,因此无法发生事件。相反,对于任何类型的动画或长时间繁重的任务(视为Thread.sleep
一个),都应该使用Swing Timers和Swing Workers 。在您的情况下, ajavax.swing.Timer
更适合。
其用法之一:
public class Blink {
private JPanel frame1;
private int pause1TimesRan;
private int pause2TimesRan;
private Timer pauser1, pauser2;
public Blink(Interface anInterface) {
this.frame1 = anInterface.getFrame1();
//Create pauser 1 with delay 200ms
pauser1 = new Timer(200, e -> {
if (pause1TimesRan == 10) {
pauser1.stop();
return;
}
Color color = randomColor();
frame1.setBackground(color);
System.out.println("Pauser #1 changed background to: " + color);
pause1TimesRan++;
});
//Create pauser 2 with delay 1000ms
pauser2 = new Timer(1000, e -> {
if (pause2TimesRan == 10) {
pauser2.stop();
return;
}
Color color = randomColor();
frame1.setBackground(color);
System.out.println("Pauser #2 changed background to: " + color);
pause2TimesRan++;
});
}
private static Color randomColor() {
return new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
}
public void blink() {
pauser1.start();
pauser2.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Interface anInterface = new Interface("Title");
anInterface.setVisible(true);
Blink blink = new Blink(anInterface);
blink.blink();
});
}
static class Interface extends JFrame {
private JPanel frame1;
public Interface(String titel) {
super(titel);
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame1 = new JPanel();
this.frame1.setPreferredSize(new Dimension(200, 200));
setLayout(new FlowLayout());
add(frame1);
this.setVisible(true);
}
public JPanel getFrame1() {
return frame1;
}
}
}
一个离题的建议是正确命名您的方法(和变量)。您调用了该方法getFrame1()
,但它实际上是 aJPanel
而不是 a JFrame
。所以,一个更好的名字可能是getPanel()
。另外,关于这SwingUtilities.invokeLater
部分,请阅读SwingUtilities.invokeLater 的作用。
推荐阅读
- c++ - 如何在 C++ 应用程序中连接到 Oracle 云数据库?
- python - 流式传输文件时如何限制内存开销?
- excel - 错误处理:如果出现运行时错误“1004”,则跳过自动填充公式
- c++ - C++ 我应该使用转发引用吗?
- javascript - 如何强制 Google Docs 从 Chrome 扩展中呈现 HTML 而不是 Canvas?
- swift - Swift - 自定义和默认 TableView 标题的混合
- javascript - React Native 无法调用 BackgroundGeolocation.start
- javascript - 如何防止用户直接访问我的html网站?
- python - 为什么当它适用于其他数组时,我会得到“RuntimeError:列需要是 1D(图像不是)”?
- linux - 是否可以配置 crontab 在夏令时生效时调整其时间?