java - 刷新 JComponent 进行倒计时不起作用

标签 java swing refresh components repaint

我制作此示例是为了在 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/

相关文章:

java - 如何减少 Spring 应用程序上下文中的重复

java - 如何从 ion 返回全局变量?

java - 在适用于Windows 10 Home 64bit的Android Studio 3.1.3中运行构建失败

java - 具有多个数据源 Oracle 和 H2 的 Spring Boot

ios - 拉动刷新不适用于无限滚动中的 JSON 请求

java - 使用jdbc向数据库中插入数据

java - 如何正确使用来自 Actionlistener 事件的输入

Java Swing 和 Windows XP 触摸事件

ios - Page Controller 和 WebView 繁琐的刷新

c# - .NET Windows 窗体刷新控件