2012-05-15 134 views
2

我有一个Java FX 2应用程序,每秒更新数百次。 我遇到了一个问题,即标签在几分之一秒内部分消隐,但这种情况经常发生。 我该如何解决这个问题?JavaFX 2空白标签刷新问题

enter image description here

+0

我的猜测是你只是淹没JavaFX事件队列或更新JavaFX应用程序线程的UI。您是否尝试更新频率较低? (例如<每秒30次)=>除非他们在慢动作相机上播放UI,否则如果每秒发生数百次,没有人会看到更新,我认为默认情况下JavaFX脉冲机制的上限为60fps )。如果降低更新频率不能解决问题,发布一个可运行的简短演示应用程序可能有助于获得答案。 – jewelsea

+0

我可以尝试调节,但不完全确定是否有简单的方法来做到这一点。我正在使用Platform.runLater进行更新。 –

回答

1

调用Platform.runLater()数百次第二是不是一个好主意。我建议你在调用Platform.runLater()来更新UI之前一起调节数据源的输入速度或者将数据批量批处理,这样Platform.runLater不会每秒调用30次以上。

我提交了一个jira请求RT-21569以改进Platform.runLater调用的文档,并考虑在底层平台中实现一个优越的runLater事件限制系统。

Richard Bair在此forum thread中给出了用于批处理runLater事件的示例解决方案。

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.scene.Scene; 
import javafx.scene.control.ListView; 
import javafx.stage.Stage; 

import java.util.LinkedList; 
import java.util.List; 
import java.util.concurrent.Semaphore; 

/** 
* 
*/ 
public class BackgroundLoadingApp extends Application { 

    private ListView<String> listView; 

    private List<String> pendingItems; 

    private Semaphore lock = new Semaphore(1); 

    protected void addItem(String item) throws InterruptedException { 
     if (Platform.isFxApplicationThread()) { 
      listView.getItems().add(item); 
     } else { 
      // It might be that the background thread 
      // will update this title quite frequently, and we need 
      // to throttle the updates so as not to completely clobber 
      // the event dispatching system. 
      lock.acquire(); 
      if (pendingItems == null) { 
       pendingItems = new LinkedList<String>(); 
       pendingItems.add(item); 
       Platform.runLater(new Runnable() { 
        @Override public void run() { 
         try { 
          lock.acquire(); 
          listView.getItems().addAll(pendingItems); 
          pendingItems = null; 
         } catch (InterruptedException ex) { 
          ex.printStackTrace(); 
         } finally { 
          lock.release(); 
         } 
        } 
       }); 
      } else { 
       pendingItems.add(item); 
      } 
      lock.release(); 
     } 
    } 

    /** 
    * The main entry point for all JavaFX applications. 
    * The start method is called after the init method has returned, 
    * and after the system is ready for the application to begin running. 
    * <p/> 
    * <p> 
    * NOTE: This method is called on the JavaFX Application Thread. 
    * </p> 
    * 
    * @param primaryStage the primary stage for this application, onto which 
    *      the application scene can be set. The primary stage will be embedded in 
    *      the browser if the application was launched as an applet. 
    *      Applications may create other stages, if needed, but they will not be 
    *      primary stages and will not be embedded in the browser. 
    */ 
    @Override public void start(Stage primaryStage) throws Exception { 
     listView = new ListView<String>(); 
     primaryStage.setScene(new Scene(listView)); 
     primaryStage.show(); 

     // Start some background thread to load millions of rows as fast as it can. But do 
     // so responsibly so as not to throttle the event thread 
     Thread th = new Thread() { 
      @Override public void run() { 
       try { 
        for (int i=0; i<2000000; i++) { 
         addItem("Item " + i); 
         if (i % 200 == 0) { 
          Thread.sleep(20); 
         } 
        } 
       } catch (InterruptedException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }; 
     th.setDaemon(true); 
     th.start(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

评论由Richard拜尔从称为论坛话题复制:

这里是模拟某些产生丰富的数据的长期运行线程的示例。 我发现它不适合我的喜好。如果Thread.sleep丢失,它仍然吞噬进程(也许这是我在这种情况下处理并发的方式)。我还发现,如果我把它减少到睡眠的“2”ms,那么我就无法抓住滚动条的拇指并将它移动。我认为这里的问题是,在事件队列中有一个用于按下和拖动的鼠标事件,但是在拖动事件之间,新项目被添加到列表中,导致拇指移动,并且因为这比我的拖动事件发生得更频繁,拇指永远不会去我想要的地方。我认为这是由于拇指位置根据行数处理的方式,不知道可以做些什么,除了应用程序调节和批量添加行之外,正如我在这里所做的那样。

+0

我无法在该线程上找到答案......唯一的答案是创建线程的负载......并不理想。 –

+0

我将引用线程中的示例解决方案复制到我的答案中。请注意,此解决方案由Richard Bair创建,不是我。 – jewelsea