首页 > 解决方案 > JavaFX,将对象字段绑定到 TreeItem 以自动更新 TreeItem

问题描述

有没有办法将对象的字段绑定到 TreeItem,以便在更改字段时,TreeItem 在 TreeView 中自动更新?我有几个字段的对象,这些字段在 TreeView 的 TreeItems 中设置。对象字段有时会通过它们的设置器以每秒 5 到 10 次的速度更新,我希望 TreeItems 在字段更改时动态更新。对此的任何帮助将不胜感激。除了重新加载整个 TreeView 之外,我似乎找不到这样做的方法。

编辑:这是现有代码...列表侦听器为播放器列表设置树视图。如果列表中的对象数量发生变化,则重新绘制树。没关系。我想要的是,如果您将代码放置在不断更改玩家属性的手柄按钮单击方法中(在一个循环中,可能每秒 2-10 次),那么随着这些属性的更改,这应该反映在树视图中。(只是一个模拟,我无法了解这些属性是如何以这种速度真正改变的)。如何做到这一点的一个例子会很棒。

package application;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import viewcontroller.PlayerViewController;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;




public class Main extends Application {
    private Stage mainStage;
    @FXML
    private AnchorPane mainView;

    @Override
    public void start(Stage mainStage) {
           this.mainStage = mainStage;
           PlayerList.playerListListener();
           this.showMainLayout();       
    }

    /**
     * shows the main screen
     */
    public void showMainLayout() {
         FXMLLoader loader = new FXMLLoader();
         loader.setLocation(Main.class.getResource("/viewcontroller/playerView.fxml"));           
         try {
            mainView = (AnchorPane) loader.load();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
         Scene scene = new Scene(mainView);
         mainStage.sizeToScene();
         mainStage.setScene(scene);
         mainStage.show();
         PlayerViewController controller = loader.getController();
         controller.setMainApp(this);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

package model;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Player {
    private StringProperty str1 = new SimpleStringProperty();
    private StringProperty str2 = new SimpleStringProperty();
    private StringProperty str3 = new SimpleStringProperty();

    public Player() {

    }

    public Player(String str1, String str2, String str3) {
        super();
        this.str1 = new SimpleStringProperty(str1);
        this.str2 = new SimpleStringProperty(str2);
        this.str3 = new SimpleStringProperty(str3);
    }
    public StringProperty str1() {
        return str1;
    }
    public String getStr1() {
        return str1.get();
    }
    public void setStr1(String str1) {
        this.str1.set(str1);
    }
    public StringProperty str2() {
        return str2;
    }
    public String getStr2() {
        return str2.get();
    }
    public void setStr2(String str2) {
        this.str2.set(str2);
    }
    public StringProperty str3() {
        return str3;
    }
    public String getStr3() {
        return str3.get();
    }
    public void setStr3(String str3) {
        this.str3.set(str3);
    }




}

package application;

import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
import model.Player;

public class PlayerList {

    private final ObservableList<Player> playerList = FXCollections.observableArrayList();

    private static PlayerList instance = new PlayerList();

    public static TreeItem<String> rootNode = new TreeItem<String>("Root");

    private PlayerList() {}

    public ObservableList<Player> getPlayerList() {
        return playerList;
    }

    public static PlayerList getInstance() {
        return instance;
    }


    public static void playerListListener() {
        //adds a list listener which reloads tree if objects are added or removed
        PlayerList.getInstance().getPlayerList().addListener((ListChangeListener<? super Player>) new ListChangeListener<Player>() {

            @SuppressWarnings("unchecked")
            public void onChanged(Change<? extends Player> change) {
                //re-sort list
                //System.out.println("List changed");
                rootNode.getChildren().clear();//clear tree before reloading on list change

                for(Player p: PlayerList.getInstance().getPlayerList()) {
                    //Parent Node
                    TreeItem<String> playerName = new TreeItem<String>(p.getStr1());
                    //Items
                    TreeItem<String> attr1 = new TreeItem<String>(p.getStr2());
                    TreeItem<String> attr2 = new TreeItem<String>(p.getStr3());

                    playerName.getChildren().addAll(attr1, attr2);
                    playerName.setExpanded(true);
                    rootNode.getChildren().add(playerName);
                    rootNode.setExpanded(true);
                }

            }
        });
    }

}

package viewcontroller;

import java.net.URL;
import java.util.ResourceBundle;

import application.Main;
import application.PlayerList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import model.Player;

public class PlayerViewController implements Initializable {
    @FXML
    private VBox vbox;
    private TreeView<String> treeView;
    public void setMainApp(Main main) {
        // TODO Auto-generated method stub

    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // TODO Auto-generated method stub
        Player p1 = new Player("Name1", "Attr1", "Attr2");
        Player p2 = new Player("Name2", "Attr1", "Attr2");
        Player p3 = new Player("Name3", "Attr1", "Attr2");
        PlayerList.getInstance().getPlayerList().addAll(p1, p2, p3);//add players to list

        treeView = new TreeView<String>(PlayerList.rootNode);
        treeView.setShowRoot(false);
        vbox.getChildren().add(treeView);//add tree view to GUI

    }
    @FXML
    private void handleButtonClick() {
        /*this method can hold code that would run in a loop, continuously setting new values
        on p1, p2, and p3 attributes and would show the tree items updating automatically*/
    }

}

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane fx:id="mainView" prefHeight="400.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="viewcontroller.PlayerViewController">
   <children>
      <VBox fx:id="vbox" layoutX="14.0" layoutY="14.0" prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <Button mnemonicParsing="false" onAction="#handleButtonClick" text="Button" />
         </children>
      </VBox>
   </children>
</AnchorPane>

标签: javajavafx

解决方案


推荐阅读