如何在不使用 Timer 而是使用 Threads 的情况下实现平滑下降的 JLabel

Posted

技术标签:

【中文标题】如何在不使用 Timer 而是使用 Threads 的情况下实现平滑下降的 JLabel【英文标题】:How to implement a smoothly falling JLabel without using Timer, but Threads instead 【发布时间】:2016-01-08 16:24:30 【问题描述】:

好的,所以我有一个空布局JPanel,其中有一个JLabelJLabel 位于 (0,0)。我要做的是在新的Thread 中使用while 循环来休眠新的Thread,然后使用SwingUtilities.invokeLaterJLabel 向下移动10px。问题是 UI 以一种滞后的方式更新。它不会每次都更新,但会跳过大量更新和大块转移。我知道我可以使用Timer 轻松做到这一点,但重点是更好地理解Threads。提前致谢!

代码:

private void start()
    Updater up = new Updater();
    up.start();

public void updatePosition()
    int y = label1.getLocation.y;
    label.setBounds(0,y+10, 10,10);

private class Updater extends Thread
    public void run()
        while(!shouldQuit)
            try
                Updater.sleep(100);
                SwingUtilities.invokeLater(new Runnable() 
                    public void run() 
                       updatePosition(); 
                    
                ); 
            catch(Exception e)
                System.out.println(e);
                  
           
    

编辑: 我通过在 updatePosition() 方法中调用一个新的 Thread 实例来替换 while 循环来让它工作,以便稍微解决问题。而且,导致问题的不仅仅是线程,所以我不得不通过调用revalidate()来强制面板重新布局它的子视图。 这是它的外观(完整的工作):

private void start()
    new Updater().start();

public void updatePosition()
    int y = label1.getLocation.y;
    label.setBounds(0,y+10, 10,10);
    panel.revalidate();
    if(!shouldQuit) new Updater().start();

private class Updater extends Thread
    public void run()
        try
            Updater.sleep(100);
            SwingUtilities.invokeLater(new Runnable() 
                public void run() 
                    updatePosition(); 
                
            ); 
        catch(Exception e)
            System.out.println(e);
           
    

【问题讨论】:

"如何在不使用 Timer 的情况下实现平滑下降的 JLabel,但使用 Threads" 为什么“不使用计时器”?为什么不在自定义绘制的面板中执行此操作,而不是尝试动态定位组件? 定时器是基于线程的,所以我认为应该有办法做到这一点,这只是一个我不知道解决方案的问题,所以值得解决。你会建议我如何在自定义涂漆面板中进行操作? “您建议我如何在自定义的绘制面板中进行此操作?” 很像 this animation,但绘制的是字符串而不是形状。实际上(检查)使用 BufferedImage 而不是自定义面板。但是一旦你有一个 Graphics 实例,它就是相同的主体。 非常感谢,我会调查的。但是,我只是不明白为什么 JLabel 不会在每次 updatePosition() 调用时更新......我觉得我错过了一些重要的东西...... 旁注:最好将 try/catch 放在 while 循环周围,而不是在其中。如果其他代码向您的线程发送中断,则意味着您被要求停止正在执行的操作。将循环放在 try/catch 中是正确响应的最简单方法。 【参考方案1】:

您应该尝试使用可见性和 GridLayout 来最大化移动。您可以使用 int var 来计算线程并将其返回到标签。同样,您应该使用您的能力来创建更新程序,更多更顺畅。只需在拖钓线程时执行 start() mwthod :-)

除了无限调用之外,您还可以进行其他操作。我认为你已经失去了类本身的继承。对象label1 一定是在战斗中丢失了。如果不是这样,那么我很确定我真的无法回答这个问题。

【讨论】:

以上是关于如何在不使用 Timer 而是使用 Threads 的情况下实现平滑下降的 JLabel的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中创建计时器而不使用 System.Timers.Timer 或 System.Threading.Timer

如何在不同步的情况下使用多个线程(2、4、8、16 个线程)循环打印字符串(10,100、1000 个循环)?

使用 Boost.Threads 的读写锁(如何转换这个简单的类)

nordic 51822 sdk. timer 的使用

定时任务,客户页面操作,使用java.util.timer(要求时间精确度不高的定时任务)

DDMS_Threads的简单使用