java - 如何使 JLabel 上的 ImageIcon 更新速度更快、延迟更短

标签 java multithreading swing jlabel imageicon

我正在尝试更新位于 JLayeredPane 上的 JLabel 上的 ImageIcon,但是在设置线程将正确状态发送到 JLabel 对象与 GUI 显示正确状态的 ImageIcon 之间存在大量延迟。以下代码是该问题的示例,查找按钮打印打开/关闭与显示图标变亮/变暗之间的时间差异。 设置线程:

new Thread(new Runnable() { // setting thread
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                while(true) {
                    System.out.println("testButton on"); // print that the button is on
                    testButton.updateState(1); // set button state to on
                    Thread.sleep(70 + random.nextInt(500)); //sleep between 70 and 570 milliseconds

                    System.out.println("testButton off");// print that the button is off
                    testButton.updateState(0); // set button state to off
                    Thread.sleep(70 + random.nextInt(500)); // sleep between 70 and 570 milliseconds

                }
            } catch(Exception e) {
                e.printStackTrace();
            }
        }

    }).start();

按钮对象:

class Button extends JLabel {

ImageIcon released;
ImageIcon pressed;
String text;

public Button(int x, int y, String text) {
    released = new ImageIcon("src/components/images/button.png");
    pressed = new ImageIcon("src/components/images/buttonDown.png");
    setBounds(x,y, 100, 100);
    this.text = text;
    setIcon(released);
}

public void updateState(int data) {
    if (data == 1) {
        setIcon(pressed);
    }
    else {
        setIcon(released);
    }
}
}

ImageIcons 只有 325 字节,那么什么可能导致延迟呢?我查阅了有关事件调度​​程序线程的信息,很多人说图像应该是瞬时绘制的。

最终目标:屏幕上有许多按钮对象,设置线程调用它们根据随机发生的操作进行更新。特定按钮对象的显示图标应在函数中设置时立即更改。设置线程不会不断循环,而是为每个发送的操作循环一次(这里循环两次只是为了显示问题)。

任何建议或尝试的事情我都会尽快测试。

编辑:最后,获取信息的线程将调用Linux中的设备驱动程序,在那里它将等待响应,并且只有当它得到响应时才需要更新窗口。据我所知,计时器用于定期更新某些内容,但我可能是错的。

最佳答案

正如在 The Event Dispatch Thread 上运行长进程的评论中所解释的那样阻止它,因此它不会响应更改。
另外,您不应该从其他(非 EDT)线程更新 Swing 组件。
您需要使用 Swing 工具,例如 SwingWorkerTimer 。 以下mcve演示使用计时器的简单幻灯片:

import java.awt.BorderLayout;
import java.io.IOException;
import java.net.URL;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.Timer;

public class ChangeButtonIcon extends JPanel{

    private final URL[] urls = {
            new URL("https://findicons.com/files/icons/345/summer/128/cake.png"),
            new URL("http://icons.iconarchive.com/icons/atyourservice/service-categories/128/Sweets-icon.png"),
            new URL("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS_FkBgG3_ux0kCbfG8mcRHvdk1dYbZYsm2SFMS01YvA6B_zfH_kg"),
    };

    private int iconNumber = 0;
    private final JButton button;
    private boolean stop = true;
    private final Random random;
    private static final int MIN_DELAY = 70, DELAY = 500;
    private Timer timer;

    public ChangeButtonIcon() throws IOException {

        random = new Random();
        button = new JButton();
        button.setIcon(new ImageIcon(urls[iconNumber]));
        button.setHorizontalTextPosition(SwingConstants.CENTER);
        button.addActionListener(e -> startStopSlideShow());
        add(button);
    }

    private void startStopSlideShow(){

        stop = ! stop;
        if(stop){
            timer.stop();
            return;
        }

        timer = new Timer( MIN_DELAY+ random.nextInt(DELAY), (e)->swapIcon());
        timer.start();
    }

    private void swapIcon() {
        iconNumber = iconNumber >= urls.length -1 ? 0 : iconNumber+1;
        button.setIcon(new ImageIcon(urls[iconNumber]));
    }

    public static void main(String[] args) throws IOException{
        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.add(new ChangeButtonIcon());
        window.add(new JLabel("Click image to start / stop"), BorderLayout.PAGE_END);
        window.pack();
        window.setVisible(true);
    }
}
<小时/>

enter image description here

关于java - 如何使 JLabel 上的 ImageIcon 更新速度更快、延迟更短,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54994628/

相关文章:

java - 在没有上下文菜单的表格中提供更多选项

java - 如何为组件设置坐标?

java - tabbedpanel - 保留在当前选项卡上,但更改选项卡的内容

java - 如何将嵌套的 Java 8 lambda 转换为 Java 1.6 兼容代码?

java - 常量和简化枚举值访问

java - 在 Java 中使变量同步且可见

java - 确定网格袋布局中的单元格是否被占用

java - 将任意参数的数组传递给通过反射调用的方法

Java并发实践Listing10.6 synchronized

sql-server - 实现每秒 30,000 次插入 SQL 的最佳方法