SwingUtilities.invokeLater on full speed thread

喜夏-厌秋 提交于 2021-02-08 06:16:27

问题


I have a thread that does display updates on my JFrame by using SwingUtilities.invokeLater. The thread's speed is adjustable, and when it set to full speed (no sleeping between updates), my program gets slowed down badly. I guess the problem is my thread is generating too much SwingUtilities.invokeLater events that JFrame's thread can not consume. So is there anything I can do on my thread to remove previously added but not consumed events? Or should I use some other ways to update JFrame without using SwingUtilities.invokeLater?

Thanks in advance.


回答1:


This might be a perfect job for SwingWorker. You can publish incremental updates, and SwingWorker will batch them to solve the performance problem:

Because the process method is invoked asynchronously on the Event Dispatch Thread multiple invocations to the publish method might occur before the process method is executed. For performance purposes all these invocations are coalesced into one invocation with concatenated arguments.

The code you want to run on the EDT, you add by implementing process(). The list of updates is passed to you in the argument.




回答2:


It sounds like you want to avoid saturating the event dispatch thread. The class javax.swing.Timer, discussed in How to Use Swing Timers, includes setCoalesce(), which "coalesces multiple pending ActionEvent firings." It may an alternative way to pace your updates.

As mentioned here, SwingWorker is limited to 33 Hz.




回答3:


Can you use a simple repaint()? The advantage of that is that multiple calls are merged into one.

(Elaboration added)

Let's say you are constantly updating your GPS location and displaying it in two text fields. Your thread to do the updating:

run() {
  while (keepGoing) {
    Point myLocation = computeMyLocation();
    locationModel.setLocation(myLocation);
    locationComponent.repaint();
  }
}

then, in MyLocationComponent

@Override
public void paintComponent(Graphics g) {
   Point myLocation = locationModel.getLocation();

   // you'd really want a NumberFormat
   latitudeTextArea.setText(String.valueOf(myLocation.y));
   longitudeTextArea.setText(String.valueOf(myLocation.x));

   super.paintComponent(g);
}

The advantage is that this splits the model from the view (if you think of the thread as the controller, this is MVC), and all the threading should work - no need for any invokeLater(). One disadvantage is that your thread needs to know all of the JComponents that need to be updated. In a "real" scenario you'd probably fire events to listeners that trigger the repaints, either from the "controller" (your thread) or from the model.

NOTE: As pointed out by @trashgod, in LocationModel, the getLocation() and setLocation() methods should be synchronized so that updates appear immediately.



来源:https://stackoverflow.com/questions/13114097/swingutilities-invokelater-on-full-speed-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!