JavaFX: Обвързване на TextArea към елемент от избран TreeItem (съдържащ се в TreeView)

Създавам следния JavAFX и като цяло съм доста нов в него. Ето как изглежда:

http://i.imgur.com/nfzQzIY.png

Както можете да видите, има TreeView отляво, както и няколко TextArea в центъра. Моля, игнорирайте останалото.

Буквено-цифровите низове отляво TreeView са обекти от клас PlugTreeItem, които създадох, за да разширя TreeItem и да имам допълнителен държач за Plug елемент, като така:

public class PlugTreeItem<T> extends TreeItem{

    private Plug plugItem = null;

    //########################### PROCS ########################################

    public PlugTreeItem(Object t, Plug pl) {
        super(t);
        plugItem = pl;
    }

    public PlugTreeItem(Object t, Node node, Plug pl) {
        super(t, node);
        plugItem = pl;
    }

    public void setPlugItem(Plug plugItem) {
        this.plugItem = plugItem;
    }

    public Plug getPlugItem() {
        return plugItem;
    }
}

И TreeView се изгражда чрез четене на Plugs от SQL DB, създаване на PlugTreeItem обекти, свързване на приставката към PlugTreeItem и след това добавяне към основния възел на дървото (който беше създаден първоначално като фиктив), от който правим TreeView: ЗАБЕЛЕЖКА: result_set съдържа SQL матрицата с резултати. MAC е полето, което съдържа адресите, които виждате вляво на екранната снимка.

treeItemRoot = new PlugTreeItem<>("Active Plugs", new Plug());          //Root of the tree, contains a dummy Plug object.
selectedTreeItem = treeItemRoot;  //Holder of our currently selected TreeItem, see Listener below.

TreeView<String> treeView = new TreeView<>(treeItemRoot);

while(result_set.next()){
    Plug pl = null;                                         
    pl = new Plug(result_set.getString("SIHUid"), result_set.getString("sensorID"), result_set.getString("Location"), result_set.getString("Appliance"), result_set.getString("Type"), result_set.getString("connection"));
    PlugTreeItem<String> pti = new PlugTreeItem(pl.getMAC(),pl);
    treeItemRoot.getChildren().add(pti);
}

И накрая, имам някои TextAreas, както виждате на екранната снимка на приложението. Искам те да отразяват елементите на избрания PlugTreeItem в TreeView, нека просто започнем с Plug MAC TextArea, който искам да отразява същата стойност, която виждате отляво.

Добавих следния слушател към selectedTreeItem, така че всеки път, когато потребителят кликне върху TreeItem, selectedTreeItem се актуализира и съдържа препратка към този конкретен PlugTreeItem:

treeView.getSelectionModel().selectedItemProperty().addListener( new ChangeListener() {     
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) { 
                selectedTreeItem = (PlugTreeItem<String>) newValue;
                System.out.println("Selection plug MAC: " + selectedTreeItem.getPlugItem().getMAC());           //MARKER: REMOVE
                // do what ever you want 
            }
        });

Надяваме се, че това прави това, което мисля, че е. Командата System.out потвърждава, че всеки път, когато щракна върху различни елементи в дървото, MAC адресът, върху който съм щракнал, се отпечатва.

Как мога да кажа на моите TextAreas "хей, слушай selectedTreeItem. Всеки път, когато се промени, получавай конкретна стойност и я задавай като свой текст"?

Опитах се да добавя втори слушател в конкретно поле на Plug, което промених от String на StringProperty, така че да стане ObservableValue. Въпреки това, дори след обвързване на textProperty на TextArea със StringProperty, това не променя съдържанието му.

Знам, че може да съм формулирал въпроса си неправилно поради размера му. Моля, не се колебайте да ме попитате за допълнителна информация или код, които може да съм пропуснал или смятате за важни.


person Dimitris Sfounis    schedule 14.02.2014    source източник
comment
Изглежда, че това повдига въпроса... Има ли смисъл да обвържете TreeItem с TextArea? В повечето случаи бих очаквал, че има повече смисъл да се обвържат и двете към основна стойност на модела. Не казвам, че този въпрос/отговор е грешен, но вероятно не е оптимален дизайн, въпреки че IMHO.   -  person Joel    schedule 22.08.2014


Отговори (1)


Не бих направил подклас на TreeItem само за това. Той е проектиран да се използва с всякакви предмети. За свързванията на TextArea просто обвържете и отменете обвързването в избрания променен слушател.

package treebind;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class TreeBind extends Application {

    @Override
    public void start(Stage primaryStage) {

        TreeItem<Plug> treeItemRoot = new TreeItem<>(new Plug("root","a"));
        TreeView<Plug> treeView = new TreeView<>(treeItemRoot);
        for (int i=0;i<10;i++)
            treeItemRoot.getChildren().add(new TreeItem<>(new Plug("name"+String.valueOf(i),"")));
        treeView.setMinWidth(150);

        final TextArea ta1 = new TextArea();

        treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if (oldValue!=null){
                    ((TreeItem<Plug>)oldValue).getValue().s1.unbindBidirectional(ta1.textProperty());
                    ta1.clear();
                }
                if (newValue!=null){
                    ta1.setText(((TreeItem<Plug>)newValue).getValue().s1.getValue());
                    ((TreeItem<Plug>)newValue).getValue().s1.bindBidirectional(ta1.textProperty());
                }
            }
        });

        HBox root = new HBox();
        root.getChildren().addAll(treeView,ta1);
        Scene scene = new Scene(root, 400, 300);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private class Plug{
        public final StringProperty name, s1;

        Plug(String name, String s1){
            this.name = new SimpleStringProperty(name);
            this.s1 = new SimpleStringProperty(s1);
        }
        @Override
        public String toString(){
            return name.getValue();
        }
    }
}
person brian    schedule 14.02.2014