我制作此示例是为了在 Java 对话消息上倒计时 30 秒。不知何故,消息组件没有刷新,直到现在我才明白为什么。如果时间正在更新并且组件已重新绘制,它应该可以正常工作。我尝试重新绘制两个组件 message.repaint()
和 messageFrame.repaint()
但都没有用。
下面的代码可以运行了。
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Chronometer {
private static final Insets INSETS = new Insets(1, 1, 1, 1);
public Chronometer(){
double timeToNext = System.currentTimeMillis() + 30000;
double timeDifference = 30000;
JFrame messageFrame = new JFrame();
messageFrame.setLayout(new GridBagLayout());
messageFrame.setTitle("Warning");
JLabel message = new JLabel("Preventing connection block. Next query in " + timeDifference/1000 + " seconds.");
messageFrame.setSize(1000,1000);
messageFrame.setLocationRelativeTo(null);
addComponent(messageFrame, message, 0, 0, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.CENTER);
messageFrame.setVisible(true);
while(timeDifference > 0){
timeDifference = timeToNext - System.currentTimeMillis();
messageFrame.repaint();
//message.repaint();
}
}
private static void addComponent(Container container, Component component, int gridx, int gridy,
int gridwidth, int gridheight, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0, 1.0,
anchor, fill, INSETS, 0, 0);
container.add(component, gbc);
}
public static void main(String[] args){
Chronometer c = new Chronometer();
}
}
最佳答案
你做错了。在构造函数中使用 while 循环不是一个好主意。 您应该改用 Timer,因为这正是 Chronometer。我带了你的代码,并用计时器快速重写了它,并利用观察者模式更新标签。
使用实现观察者接口(interface)的 Controller 。
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Controller implements Observer {
private static final Insets INSETS = new Insets(1, 1, 1, 1);
private Chronometer chrono = new Chronometer();
private final JLabel message = new JLabel();
public Controller() {
final JFrame messageFrame = new JFrame("Warning");
messageFrame.setLayout(new GridBagLayout());
messageFrame.setSize(1000,1000);
messageFrame.setLocationRelativeTo(null);
addComponent(messageFrame, message, 0, 0, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.CENTER);
messageFrame.setVisible(true);
chrono.addObserver(this);
}
public void startChrono(int delay) {
chrono.startCountDown(delay);
}
public void refreshLabel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
message.setText("Preventing connection block. Next query in " + chrono.getTime()/1000 + " seconds.");
}
});
}
@Override
public void update(Observable o, Object arg) {
refreshLabel();
}
private static void addComponent(Container container, Component component, int gridx, int gridy, int gridwidth, int gridheight, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0, 1.0,anchor, fill, INSETS, 0, 0);
container.add(component, gbc);
}
}
创建一个带有计时器的计时器类:
import java.util.Observable;
import java.util.Timer;
import java.util.TimerTask;
public class Chronometer extends Observable {
private Timer timer = new Timer();
private final int startTime = 30000;
private int time = 30000;
public void decreaseTime() {
if (time > 0) time--;
}
public int getTime() {
return time;
}
public void reset() {
time = startTime;
}
public void startCountDown(int delay) {
timer.schedule(new TimerTask() {
@Override
public void run() {
decreaseTime();
setChanged();
notifyObservers();
}
}, delay,1);
}
}
最后启动你的 Controller
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Controller().startChrono(1);
}
});
}
}
关于java - 刷新 JComponent 进行倒计时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20163323/