有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使GUI更具响应性

我的程序将物理模拟可视化(基本上)。现在,它可以工作,但可能会变得非常无响应,我想我知道为什么——在事件线程上进行了太多(读取:all)计算

当按下“播放”按钮时,会创建一个SwingTimer,它会定期唤醒并调用updateTime()——目前为止一切正常。问题是updateTime()迭代每个依赖时间的对象,并告诉它以适当的数量(实时经过的时间,或每个滴答的任意时间单位)在时间上向前传播自己。这些计算以及随后的GUI更新都在事件调度线程上

因此,我希望尽可能地减少这种计算,我认为SwingWorker是一种可行的方法,但我不确定如何将它们应用到现有代码中。我不能让现有的类扩展SwingWorker,因为它们中的许多已经扩展了其他类

到目前为止,我最好的想法是为每个要实现的时间相关对象创建一个接口。接口将指定两种方法,calcUpdateTime()drawUpdateTime()。我会将他们当前的updateTime()方法分为物理计算(分为calc_)和GUI更新(分为draw_)。然后我只创建一个SwingWorker类,它在构造函数中接受TimeDependant对象,它的doInBackground将调用calcUpdateTime,而done将调用drawUpdateTime。这样我就可以替换所有出现的

myObj.updateTime(currentTime);

new MySwingWorker(myObj, currentTime).execute();

我想用它来运行这个想法,因为它感觉不太对,而且它希望避免重构整个项目,只是为了发现我一开始的想法不好。另外,每个滴答声可能会产生几十个MySwingWorker不是一个坏主意吗

谢谢你读到这里


共 (1) 个答案

  1. # 1 楼答案

    我使用Swing timer的体验(性能方面)很差。由于Swing中的所有事件都使用同一个线程,因此它似乎有很多意外的延迟

    我还建议你相信自己的直觉,每滴答都会出现多个swing worker实例:这听起来也不对。(根据SwingWorker文档,它被设计为只运行一次,所以你不一定能安全地重用它)

    一个可能做你需要的事情的计时器是java.util.Timer。这有很多用于指定超时的选项,尽管这取决于计时模拟的保真度,即使这样也可能不合适。(例如:如果你想让它实时运行,但你的计算时间实际上比实时时间长,那么它应该怎么做?慢慢运行,或者开始跳过时间步?)

    所以,由于不知道你的计算/绘图程序具体涉及什么,我暂时建议尝试java.util.Timer。当它过期时(根据“实时乘法器”,在您认为合适的任何超时时间之后),运行所有的计算,然后将结果返回给EDT线程进行绘制(例如,将它们包装在SwingUtilities.invokeLater()中)

    当然,如果EDT想要引用与计算线程相同的对象,这可能会引入锁定问题。理想情况下,如果calc线程可以将不可变的结果传递给EDT,就不必引入锁

    (免责声明:除了一个用于GUI,一个用于计算之外,上述任何一个都没有真正考虑多个内核/处理器。如果你想并行化应用程序,这可能不是一个合适的解决方案)