簡體   English   中英

如何監聽特定節點的JavaFX SceneGraph的可見更改

[英]How to listen to visible changes to the JavaFX SceneGraph for specific node

我們在JavaFX中創建了一個小型繪畫應用程序。 出現了一個新的要求,即我們必須警告用戶,他做了一些尚未持久的更改並詢問他,用戶是否願意在關閉之前先保存。

示例快照:

畫布圖像

不幸的是,有很多不同的節點,節點可以通過多種方式進行更改,例如Polygon點可以移動。 可以拖動節點本身。 它們可以旋轉等等。 因此,在為一個Node對象的每個可能的更改觸發一個極好的事件之前,我想問一下,如果有人可能知道如何簡化這種方法。 我很好奇,如果有任何監聽器,我可以在JavaFX的場景圖中監聽canvas對象的任何更改。

特別是因為我只是想知道是否有任何改變,而不是真的需要知道具體的變化。

此外,我也不希望得到每個單獨的事件,如簡單的選擇,這會導致在所選節點周圍顯示邊框(如圖中所示),這並不意味着用戶必須保存他的離開前申請。

有人有想法嗎? 或者我真的需要為節點內的每一次更改觸發事件嗎?

我認為你正在以錯誤的方式解決這個問題。 屏幕上顯示的節點應該只是底層模型的直觀表示。 您真正需要知道的是底層模型已經改變。

例如,如果您正在編寫文本編輯器,則屏幕上顯示的文本將由某種模型支持。 我們假設模型是一個String 您不需要檢查屏幕上顯示的任何文本節點是否已更改,您只需要將原始字符串數據與當前字符串數據進行比較,以確定是否需要提示用戶進行保存。

Benjamin的答案可能是最好的答案:您應該使用底層模型,該模型可以輕松檢查相關狀態是否已更改。 在開發應用程序的某個時刻,您將會發現這是正確的做事方式。 好像你已經達到了那一點。

但是,如果你想延遲不可避免地重新設計你的應用程序(當你達到這一點時讓它變得更加痛苦;)),這是你可能考慮的另一種方法。

顯然,你有某種Pane正在拿着被繪制的物體。 用戶必須創建這些對象,並在某些時候將它們添加到窗格中。 只需創建一個處理該添加的方法,並在執行時注冊具有感興趣屬性的失效偵聽器。 結構看起來像這樣:

private final ReadOnlyBooleanWrapper unsavedChanges = 
    new ReadOnlyBooleanWrapper(this, "unsavedChanged", false);

private final ChangeListener<Object> unsavedChangeListener = 
    (obs, oldValue, newValue) -> unsavedChanges.set(true);

private Pane drawingPane ;

// ...

Button saveButton = new Button("Save");
saveButton.disableProperty().bind(unsavedChanges.not());

// ...
@SafeVarArgs
private final <T extends Node> void addNodeToDrawingPane(
        T node, Function<T, ObservableValue<?>>... properties) {

    Stream.of(properties).forEach(
        property -> property.apply(node).addListener(unsavedChangeListener));
    drawingPane.getChildren().add(node);
}

現在你可以做點什么了

    Rectangle rect = new Rectangle();

    addNodeToDrawingPane(rect, 
            Rectangle::xProperty, Rectangle::yProperty, 
            Rectangle::widthProperty, Rectangle::heightProperty);

    Text text = new Text();
    addNodeToDrawingPane(text, 
            Text::xProperty, Text::yProperty, Text::textProperty);

即,您只需指定添加新節點時要觀察的屬性。 您可以創建一個刪除偵聽器的remove方法。 在您已經擁有的內容之上的額外代碼量是非常小的,因為(可能,我還沒有看到您的代碼)是重構。

同樣,你應該有一個單獨的視圖模型,等等。我想發布這個以表明@kleopatra對問題的第一個評論(“監聽相關狀態的失效”)如果你接近,不一定涉及很多工作它以正確的方式。 起初,我認為這種方法與@Tomas Mikula提及撤消/重做功能不相容,但你甚至可以使用這種方法作為基礎。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM