如何使JLabel上的ImageIcon更新更快,延迟更少 [英] How to make ImageIcon on JLabel update faster with less latency

查看:118
本文介绍了如何使JLabel上的ImageIcon更新更快,延迟更少的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试更新位于JLayeredPane上的JLabel上的ImageIcon,但是在设置线程将正确的状态发送到JLabel对象与GUI显示正确状态的ImageIcon之间会有很多延迟.下面的代码是该问题的一个示例,查找按钮的打印处于打开/关闭状态与显示的图标变浅/变暗之间的时间差. 设置线程:

I am trying to update an ImageIcon on a JLabel which sits on a JLayeredPane, but there is a lot of latency between when the setting thread sends the proper state to the JLabel object and when the GUI displays the ImageIcon of the proper state. The following code is an example of the issue, look for the difference in time between the print of the button being on/off and when the displayed icon gets lighter/darker. The setting thread:

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个字节,那么可能导致延迟的原因是什么?我抬头看了有关Event Dispatcher Thread的消息,许多人说应该立即绘制图像.

The ImageIcons are only 325 bytes, so what might be causing the latency? I looked up about the Event Dispatcher Thread and many people say it should be instantaneous for an image to get painted.

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

End goal: Have many button objects on screen with the setting thread calling them to update based on randomly occurring actions. The displayed icon for a specific button object should change immediately as it is set in the function. The setting thread will not be constantly looping, instead loop once for every action sent (it is twice here just to show the issue).

我会尽快测试任何建议或尝试的东西.

Any suggestions or things to try I will test as soon as I can.

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

In the end the thread that gets the information will call to a device driver in Linux where it will wait for a response and only when it gets a response will it need to update the window. From what I know timer is used to update something at regular intervals, but I am likely wrong.

推荐答案

如在 SwingWorker 计时器. 以下 mcve 演示了使用Timer的简单幻灯片:

As explained in the comments running long processes on the The Event Dispatch Thread blocks it, so it does not respond to changes.
Also you are not suppose to update Swing components from other (not EDT) threads.
You need to use Swing tools like SwingWorker or Timer. The following mcve demonstrates a simple slide-show using Timer:

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);
    }
}



这篇关于如何使JLabel上的ImageIcon更新更快,延迟更少的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆