コードでは、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);
}
}
}
タイムラインの使用platform.runLaterと同じ問題が発生します。アプリケーションスレッドが何をしていても、3つすべてが作成されて表示されます。私の質問では、Thread.sleepを使用しましたが、私の実際のアプリケーションはいくつかのファイルをダウンロードし、他のファイル処理を行います。 「ダウンロード開始」、「ダウンロード終了」などの通知ができるようにしたいしたがって、最後に一度にすべての通知をユーザーに表示することは、あまり有益ではありません。私はタイムラインに慣れていないので、私はこれをちょっと試して、私が望むように行動できるかどうかを見ていきます。 – docb45
@ docb45「タイムライン」は悪い考えでした(私はどうにかして、「遅延をシミュレートするThread.Sleep *」の部分に適切な注意を払っていませんでした)。答えを修正しました... – fabian
素晴らしい作品!私はタスクで演奏しましたが、通知を表示するためにリスナーを追加する方法については欠けていました。これは完全に機能します。 – docb45