JavaFX 2空白标签刷新问题 [英] JavaFX 2 blank label refresh issue

查看:52
本文介绍了JavaFX 2空白标签刷新问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Java FX 2应用程序,它每秒更新数百次. 我遇到一个问题,其中标签被部分消隐了不到一秒钟的时间,但是这种情况经常发生. 我该如何解决?

I have a Java FX 2 app which is updating hundreds of times a second. I'm getting a problem where the labels are partially blanked for a fraction of a second but this happens fairly often. How do I fix this?

推荐答案

调用

Calling Platform.runLater() hundreds of times a second is not a good idea. I advise you throttle the input speed of your data source or batch your data together before invoking Platform.runLater() to update your UI, such that Platform.runLater isn't invoked > 30 times a second.

我提交了一个jira请求 RT-21569 ,以改进关于Platform.runLater调用,并考虑在基础平台中实现高级runLater事件限制系统.

I filed a jira request RT-21569 to improve the documentation on the Platform.runLater call and consider implementing a superior runLater event throttling system in the underlying platform.

Richard Bair在此论坛线程中给出了批处理runLater事件的示例解决方案. .

A sample solution for batching runLater events is given by Richard Bair in this forum thread.

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 Bair的评论来自引用的论坛主题:

Comments by Richard Bair copied from the referred forum thread:

这里是一个示例,该示例模拟一些长时间运行的线程产生大量数据. 我发现这不太符合我的喜好.如果缺少Thread.sleep,它仍然会淹没进程(也许在这种情况下,这是我处理并发的方式).我还发现,如果将睡眠时间减少到"2"毫秒,那么我将无法抓住滚动条拇指并四处移动.我认为这里的问题是在事件队列中有一个用于按下和拖动的鼠标事件,但是在拖动事件之间,新项目被添加到列表中,从而导致拇指移动,并且由于这种情况比我的拖动事件更频繁地发生,永远不会去我想要的地方.我认为这是由于基于行数处理拇指位置的方式所致,除了在应用程序中像我在此处那样对要添加的行进行节流和批处理之外,不确定如何处理.

Here is an example that simulates some long running thread producing copious amounts of data. I found that it wasn't working quite to my liking. If the Thread.sleep is missing, it still swamps the process (perhaps it is the way I'm handling the concurrency in this case). I also found if I reduced it to "2" ms of sleeping then I couldn't grab the scroll bar thumb and move it around. I think the problem here is that there is a mouse event in the event queue for the press and drag, but between drag events new items are added to the list causing the thumb to move and since this happens more frequently than my drag events the thumb never goes where I want it to be. This I think is due to the way the thumb position is handled based on the number of rows, not sure what can be done about it except for the application to throttle and batch up the rows being added as I do here.

这篇关于JavaFX 2空白标签刷新问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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