2016-10-22 17 views
0

私はJavaFXを初めて使い、ControlsFX Notificationを使用するときにマイナーな問題でハングアップしました。例えば、いくつかのファイルをダウンロードしている、より長い実行中のタスクの間に、私はダウンロードが始まると通知を表示したいと思います。しかし、これを試してみると、タスクが完了した後にのみ通知が表示されます。ここでJavafx controlsfx show()が呼び出されたときに通知がすぐに表示されない

を実行するためのいくつかのコードの遅延をシミュレートするの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ミリ秒を作成されていますが、すぐに表示されていません。すぐに表示するにはどうしたらいいですか?

答えて

1

コードでは、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); 
     } 
    } 
} 
+0

タイムラインの使用platform.runLaterと同じ問題が発生します。アプリケーションスレッドが何をしていても、3つすべてが作成されて表示されます。私の質問では、Thread.sleepを使用しましたが、私の実際のアプリケーションはいくつかのファイルをダウンロードし、他のファイル処理を行います。 「ダウンロード開始」、「ダウンロード終了」などの通知ができるようにしたいしたがって、最後に一度にすべての通知をユーザーに表示することは、あまり有益ではありません。私はタイムラインに慣れていないので、私はこれをちょっと試して、私が望むように行動できるかどうかを見ていきます。 – docb45

+0

@ docb45「タイムライン」は悪い考えでした(私はどうにかして、「遅延をシミュレートするThread.Sleep *」の部分に適切な注意を払っていませんでした)。答えを修正しました... – fabian

+0

素晴らしい作品!私はタスクで演奏しましたが、通知を表示するためにリスナーを追加する方法については欠けていました。これは完全に機能します。 – docb45

0

あなたはどんなコンテキストも表示しませんが、あなたのコードはJavaFX GUIスレッドをブロックしていると言います。上のコードを別のスレッドで実行し、各通知の作成をPlatform.runLater呼び出しでラップする必要があります。 また、アニメーションタイマーやタイムラインを使用することもできます。その後、別のスレッドは必要なく、Thread.sleepは必要ありません。

+0

ああ、はい、私は完全にPlatform.runLaterを忘れていました。私はそれを試してみましたが、私がそこに遭遇した問題は、アプリケーションスレッドが終了した後にすべての通知が作成されることでした。上記と一緒に**は別々に**作成され、同時にすべてが**最後に**表示されます**。したがって、3秒間表示する必要がある最初のスリープコールは、3回のスリープコールを待たなければならず、次に1.5秒間だけ表示されます。 platform.runLaterを使用すると、3つすべてが3秒間表示されていますが、アプリケーションスレッドが終了した後にのみ同時に作成されます。 – docb45

関連する問題