2016-03-27 11 views
0

私のアプリケーションでは、ShopLogController.javaで制御される単純なログウィンドウを設計しました。JavaFXウィンドウが開いている間にXミリ秒ごとに操作を実行します

log window

このウィンドウはShopLogShopLogControllerと混同すべきでない)クラスからのログ情報を取り、それを表示します。しかし、ShopLog自体は、存在するすべてのオブジェクトによって変更される可能性があります。したがって、変更された内容があるかどうかを確認する方法は、ログウィンドウの内容をShopLogクラス内のテキストログと一致させるためです。私がこれまでに調査し

オプション:

  • はいつでもログが変更と呼ばれるShopLogControllerの公共update()機能を実装します。 これは問題なく動作しますが、IMOはGUI /ロジック/パーシスタンス層の厳密な分離に違反します。これは、ロジック層がGUIの更新を促すためにGUIを明示的に呼び出すためです。 (あなたはこれが層-別離の違反ではないと信じているなら、理由を説明してください)

  • は独自のスレッドで実行され、すべてのXミリ秒以上からupdate()を呼び出すUpdaterオブジェクトのいくつかの種類を実装します。 JavaFXではこれが許可されていません。これは、java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-#を返します。

  • 対応するコントローラ内でスレッドを開始します。これも正常に動作しますish。唯一の問題は、アップデートが決して終了しないループwhile(true)にあることです。このループを終了するには、実行可能なon-closeメソッドが必要です。私は、アプリケーション全体ではなく、単一のウィンドウに対するこのような解決策を認識していません。どのように私は明示的に外部からそうするように、それを求めることなく、私のログ(および他の)窓(複数可)の更新を行うことができます

stop()を参照してください)。まだコントローラをウィンドウを閉じるときに終了させますか?

としては、関連するオブジェクトのコードを要請:

shopLogController

shopLog

構造は、それがここになるにつれてなどの基本です。 Stringがにあり、変更するとupdate()ShopLogControllerが呼び出されます。また、ShopLogからコントローラの関数を明示的に呼び出すことは避けたいと思います。これは、ログウィンドウがまだ開かれていないなど、ShopLogが保証されていないためです。

PS:これは実際にはany実行可能な解決策を見つけることではなく、優雅なものを見つけることです。

+0

ログがテキスト領域に表示されているようです。テキスト領域の 'textProperty()'にリスナーを追加するだけではどうですか?あるいは、私は本当にその質問を理解していないかもしれません...? –

+0

問題を正しく伝えたかどうかわかりません: Stringを保持するShopLogクラスがあります。ログの文字情報を表します。 shopLogControllerは、GUIウィンドウが処理するものだけを処理します。 文字列の変更が最初に起こりました。コントローラーのTextAreaを – nitowa

+0

で更新したいので、 'String'の代わりに' StringProperty'を使用し、それにリスナーを登録します。問題の内容を説明するコードを投稿することができます。 –

答えて

0

あなたはこのようなあなたのログ(モデル)を実装することができます

public class ShopLog { 

    private final ReadOnlyStringWrapper logText = new ReadOnlyStringWrapper(); 

    public ReadOnlyStringProperty textProperty() { 
     return logText.getReadOnlyProperty(); 
    } 
    public final String getText() { 
     return textProperty().get(); 
    } 

    // Implement as many methods like this as your API needs: 
    public void log(String logMessage) { 
     logText.set(logText.get() + "\n" + logMessage); 
    } 
} 

明らかに、このクラスは何のビューの知識(またはビューのコントローラ/プレゼンターを)持っていないので、ビューとモデルの分離に違反しません。

あなたのコントローラは次のようになります。

public class ShopLogController { 

    private ShopLog log ; 

    @FXML 
    private TextArea logDisplay ; 

    public void setShopLog(ShopLog log) { 
     logDisplay.textProperty().bind(log.textProperty()); 
    } 
} 

をだから今log(...)メソッドが呼び出されたときにShopLogに、ビュー内のテキスト領域に自動的に通知される(経由結合)、およびテキストを更新します表示されます。バインディングは、モデルではなくコントローラから管理され、適切な懸念事項の分離が維持されます。任意のポーリング(任意のポーリング間隔と管理のためのスレッド化)は必要ありません。

データを1つのモノリシックな文字列として格納し、文字列連結を使用してテキスト領域を使用して更新するため、これは特にスケーラブルなソリューションではありません。私はこの実装を、あなたのコメントとスクリーンショットに基づいて使用しているように見せました。代わりにObservableList<String> logMessagesを使用するモデルなど、他の一般的な実装の使用を検討することもできます。

+0

これは私が探していたソリューションの種類です、ありがとうございます! 私は基本的にリストの周りで同じ問題を抱えているので、そこにも私の問題を解決しました。 :) – nitowa

関連する問題