调用 show() 时,Javafx controlsfx 通知不会立即显示
Javafx controlsfx Notification doesn't display immediately when show() is called
我是 JavaFX 的新手,在使用 ControlsFX 通知时遇到了一个小问题。在一些较长的 运行ning 任务中(例如下载一些文件),我想在下载开始时显示一个通知,并在下载完成时再次显示;然而,当我尝试这个时,通知都只在任务完成后显示。
这是一个示例,其中 Thread.Sleep 模拟了一些代码到 运行:
的延迟
Notifications.create() .title("Title Text") .text("Hello World 1!") .darkStyle() .show();
Thread.sleep(500);
Notifications.create() .title("Title Text") .text("Hello World 2!") .darkStyle() .show();
Thread.sleep(500);
Notifications.create() .title("Title Text") .text("Hello World 3!") .darkStyle() .show();
Thread.sleep(500);
当这 运行 秒时,所有通知一次显示,而不是相隔半秒。
Here's an image of what the notifications look like in the lower right corner
However, they fade away a half second apart..
所以它们是相隔 500 毫秒创建的,但不会立即显示。如何让它们立即显示?
您没有显示任何上下文,但我会说您的代码只是阻塞了 JavaFX GUI 线程。您必须在单独的线程中执行上面的代码,并将每个通知创建包装在 Platform.runLater 调用中。
或者,您也可以使用 AnimationTimer 或时间轴。那么您将不需要单独的线程,也不需要 Thread.sleep.
在您的代码中,您阻塞了负责重绘 UI 的 JavaFX 应用程序线程。这样,GUI 中的任何更改都将不可见,事件也不会被处理,等等。
您可以使用 Task
并将侦听器添加到 message
属性 以显示消息。此 属性 的更新保证在应用程序线程上执行。唯一的缺点是为了快速更新 属性 可以跳过一些通知。
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
// update message property
updateMessage("Hello World 1!");
Thread.sleep(500);
updateMessage("Hello World 2!");
Thread.sleep(500);
updateMessage("Hello World 3!");
Thread.sleep(500);
return null;
}
};
// display message changes as notifications
task.messageProperty().addListener((observable, oldMessage, newMessage) ->
Notifications.create().title("Title Text").text(newMessage).darkStyle().show());
// execute long running task on background thread
new Thread(task).start();
如果您需要显示每条消息,您应该使用 Platform.runLater
来触发通知。
Thread thread = new Thread(new Runnable() {
private void postMessage(final String message) {
Platform.runLater(() -> Notifications.create().title("Title Text").text(message).darkStyle().show());
}
@Override
public void run() {
try {
postMessage("Hello World 1!");
Thread.sleep(500);
postMessage("Hello World 2!");
Thread.sleep(500);
postMessage("Hello World 3!");
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(NotificationsTestMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
thread.start();
注意不要经常使用Platform.runLater
。如果有很多更新,有时最好将它们分组。但是,在这种情况下,您可能无论如何都不想使用通知,因为要显示所有这些通知会很简单。不过这里有一些代码演示了对更新进行分组:
private final List<String> messageQueue = new ArrayList<>();
private boolean updating;
private final Runnable updater = () -> {
synchronized (messageQueue) {
for (String message : messageQueue) {
Notifications.create().title("Title Text").text(message).darkStyle().show();
}
messageQueue.clear();
updating = false;
}
};
private void postMessage(String message) {
synchronized (messageQueue) {
messageQueue.add(message);
if (!updating) {
updating = true;
Platform.runLater(updater);
}
}
}
我是 JavaFX 的新手,在使用 ControlsFX 通知时遇到了一个小问题。在一些较长的 运行ning 任务中(例如下载一些文件),我想在下载开始时显示一个通知,并在下载完成时再次显示;然而,当我尝试这个时,通知都只在任务完成后显示。
这是一个示例,其中 Thread.Sleep 模拟了一些代码到 运行:
的延迟 Notifications.create() .title("Title Text") .text("Hello World 1!") .darkStyle() .show();
Thread.sleep(500);
Notifications.create() .title("Title Text") .text("Hello World 2!") .darkStyle() .show();
Thread.sleep(500);
Notifications.create() .title("Title Text") .text("Hello World 3!") .darkStyle() .show();
Thread.sleep(500);
当这 运行 秒时,所有通知一次显示,而不是相隔半秒。
Here's an image of what the notifications look like in the lower right corner
However, they fade away a half second apart..
所以它们是相隔 500 毫秒创建的,但不会立即显示。如何让它们立即显示?
您没有显示任何上下文,但我会说您的代码只是阻塞了 JavaFX GUI 线程。您必须在单独的线程中执行上面的代码,并将每个通知创建包装在 Platform.runLater 调用中。 或者,您也可以使用 AnimationTimer 或时间轴。那么您将不需要单独的线程,也不需要 Thread.sleep.
在您的代码中,您阻塞了负责重绘 UI 的 JavaFX 应用程序线程。这样,GUI 中的任何更改都将不可见,事件也不会被处理,等等。
您可以使用 Task
并将侦听器添加到 message
属性 以显示消息。此 属性 的更新保证在应用程序线程上执行。唯一的缺点是为了快速更新 属性 可以跳过一些通知。
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
// update message property
updateMessage("Hello World 1!");
Thread.sleep(500);
updateMessage("Hello World 2!");
Thread.sleep(500);
updateMessage("Hello World 3!");
Thread.sleep(500);
return null;
}
};
// display message changes as notifications
task.messageProperty().addListener((observable, oldMessage, newMessage) ->
Notifications.create().title("Title Text").text(newMessage).darkStyle().show());
// execute long running task on background thread
new Thread(task).start();
如果您需要显示每条消息,您应该使用 Platform.runLater
来触发通知。
Thread thread = new Thread(new Runnable() {
private void postMessage(final String message) {
Platform.runLater(() -> Notifications.create().title("Title Text").text(message).darkStyle().show());
}
@Override
public void run() {
try {
postMessage("Hello World 1!");
Thread.sleep(500);
postMessage("Hello World 2!");
Thread.sleep(500);
postMessage("Hello World 3!");
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(NotificationsTestMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
thread.start();
注意不要经常使用Platform.runLater
。如果有很多更新,有时最好将它们分组。但是,在这种情况下,您可能无论如何都不想使用通知,因为要显示所有这些通知会很简单。不过这里有一些代码演示了对更新进行分组:
private final List<String> messageQueue = new ArrayList<>();
private boolean updating;
private final Runnable updater = () -> {
synchronized (messageQueue) {
for (String message : messageQueue) {
Notifications.create().title("Title Text").text(message).darkStyle().show();
}
messageQueue.clear();
updating = false;
}
};
private void postMessage(String message) {
synchronized (messageQueue) {
messageQueue.add(message);
if (!updating) {
updating = true;
Platform.runLater(updater);
}
}
}