JavaFX TreeView选择(TreeItem<;Object>;)未按预期工作

JavaFX TreeView选择(TreeItem<;Object>;)未按预期工作,java,javafx,treeview,Java,Javafx,Treeview,过去我在这个论坛上读到了很多提示和技巧。 现在我试着问我的第一个问题:——) 我对JavaFX有点陌生,但对Java并不陌生。我正在尝试将一个应用程序从Swing移植到JavaFX,这样它将更加新奇和可定制 这个程序的主要任务是显示两棵树并比较它们。 为了更方便,我在旧的应用程序中实现了一个侦听器和celleditor来可视化差异,当您在一个树中选择一个项目时,它会尝试在另一个树中找到相应的项目。如果它不可见,它将可见 显示当前应用程序的一个屏幕截图: 开始后,它看起来像这样 在左侧选择时,在右

过去我在这个论坛上读到了很多提示和技巧。 现在我试着问我的第一个问题:——)

我对JavaFX有点陌生,但对Java并不陌生。我正在尝试将一个应用程序从Swing移植到JavaFX,这样它将更加新奇和可定制

这个程序的主要任务是显示两棵树并比较它们。 为了更方便,我在旧的应用程序中实现了一个侦听器和celleditor来可视化差异,当您在一个树中选择一个项目时,它会尝试在另一个树中找到相应的项目。如果它不可见,它将可见

显示当前应用程序的一个屏幕截图: 开始后,它看起来像这样 在左侧选择时,在右侧自动选择,反之亦然:

现在,我尝试在JavaFX中实现相同的功能: 但使用此代码:

public void setOtherTree(TreeView<CompareNode> otherTree) {
    if (log.isTraceEnabled()) {
        log.trace("setOtherTree("+otherTree+")");
    }       
    this.otherTree = otherTree;

    tree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
    tree.getSelectionModel().selectedItemProperty().addListener((observable,oldValue,newValue) -> selectInOtherTree(newValue));
}

public void selectInOtherTree(TreeItem<CompareNode> newValue) {
    if (log.isDebugEnabled()) {
        log.debug(logPrefix + " " + String.format("selectInOtherTree:newValue".replaceAll(", ", "=%s, ") + "=%s", newValue));
    }       
    otherTree.getSelectionModel().clearSelection();
    otherTree.getSelectionModel().select(newValue);
}
public void setOtherTree(TreeView otherTree){
if(log.isTraceEnabled()){
trace(“setOtherTree(“+otherTree+”);
}       
this.otherTree=otherTree;
tree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tree.getSelectionModel().SelectEditeProperty().addListener((可观察、旧值、新值)->selectInOtherTree(新值));
}
public void选择其他树(TreeItem newValue){
if(log.isDebugEnabled()){
log.debug(logPrefix+“”+String.format(“selectInOtherTree:newValue.replaceAll”(“,”,“=%s,”)+“=%s”,newValue));
}       
otherTree.getSelectionModel().clearSelection();
otherTree.getSelectionModel().select(newValue);
}
它总是在索引基础上选择项目:

我是遗漏了什么还是JDK1.8u45(我目前正在使用)中的一个bug

类CompareNode覆盖toString、equals和hash

正如我所看到的,我需要10个声誉来发布图片:-(,所以我希望我的话能足够详细地解释它,或者你可以点击链接。对此感到抱歉。

非常感谢您的帮助

问候 安德烈亚斯

2015-07-10更新: 显示旧应用程序的两个屏幕截图:

以及新应用程序的屏幕截图:

感谢您的好评:-)

2015-09-22更新

同时,我创建了一个小的演示应用程序来演示它

TreeItemString.java

package application;
import javafx.scene.control.TreeItem;
public class TreeItemString extends TreeItem<String> {  
    public TreeItemString(String value) {
    this.setValue(value);
}   
@Override
public boolean equals(Object obj) {
    if (obj == null) {
        return false;
    }
    return this.getValue().equals(((TreeItemString) obj).getValu());
}   
@Override
public String toString() {
    return this.getValue();
}   
@Override
public int hashCode() {     
    return this.getValue().hashCode();
}
}
包应用;
导入javafx.scene.control.TreeItem;
公共类TreeItemString扩展TreeItem{
public TreeItemString(字符串值){
这个.setValue(值);
}   
@凌驾
公共布尔等于(对象obj){
if(obj==null){
返回false;
}
返回此.getValue().equals(((TreeItemString)obj.getValu());
}   
@凌驾
公共字符串toString(){
返回这个.getValue();
}   
@凌驾
public int hashCode(){
返回此.getValue().hashCode();
}
}
MainApp.java

package application;    
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {    
    public void selectInOtherTree(TreeItem<String> toSelect, TreeView otherTree, TreeView thisTree) {
        System.out.println("Othertree : " + toSelect);
        System.out.println("Me : " + thisTree.getRow(toSelect));
        System.out.println("Other: " + otherTree.getRow(toSelect));
        otherTree.getSelectionModel().select(toSelect);
    }   
    public TreeItemString newRoot(TreeView<String> tree, Label label, String labelPrefix) {
        //Create TreeItems for the Hierarchy of the TreeView
        TreeItemString royalRoot = new TreeItemString("Queen Elizabeth - Prince Philip");    
        TreeItemString Charlie  = new TreeItemString("Prince Charles - Princess Diana");
        TreeItemString Annie = new TreeItemString("Princess Anne - Mark Phillips");
        TreeItemString Andy = new TreeItemString("Prince Andrew - Sarah Ferguson");
        TreeItemString Eddie = new TreeItemString("Prince Edward - Sophie");        
        //Populate the TreeItem to be used as the root with the other TreeItems
        royalRoot.getChildren().addAll(Charlie, Annie, Andy, Eddie);
        //Populate the other TreeItems with more TreeItems 
        //to build the family tree
        Charlie.getChildren().addAll(
                new TreeItemString("Prince William"), 
                new TreeItemString("Prince Henry"));        
        Annie.getChildren().addAll(
                new TreeItemString("Peter Phillips"), 
                new TreeItemString("Zara Phillips"));        
        Andy.getChildren().addAll(
                new TreeItemString("Princess Beatrice"), 
                new TreeItemString("Princess Eugenie"));        
        Eddie.getChildren().addAll(
                new TreeItemString("Lady Louise"), 
                new TreeItemString("Viscount Severn"));        
        return royalRoot;
    }   
    @Override
    public void start(Stage primaryStage) {        
       final String leftTreeLabelPrefix= "Selected Tree Item From left Tree: \n";
       final String rightTreeLabelPrefix = "Selected Tree Item From right Tree: \n";       
        //Use HBOX and VBOX layout panes to space out the controls
        //in a single row
        HBox treeBox = new HBox();
        VBox labelBox = new VBox(30);
        HBox controlBox = new HBox(10);        
        //Create labels to highlight the selected items from the TreeViews
        final Label leftTreeLabel = new Label(leftTreeLabelPrefix);
        final Label rightTreeLabel = new Label(rightTreeLabelPrefix);
        //Create and empty TreeView
        TreeView<String> leftTree = new TreeView<String>();                
        //Use the setRoot method to set the root TreeItem
//        duckTree.setRoot(duckRoot);
        leftTree.setRoot(newRoot(leftTree,leftTreeLabel, "Selected Tree Item From left Tree: \n"));        
        //Create a TreeView using the root TreeItem
        TreeView<String> rightTree = new TreeView<String>();
        rightTree.setRoot(newRoot(rightTree,rightTreeLabel, "Selected Tree Item From right Tree: \n"));        
        rightTree.getSelectionModel().selectedItemProperty().addListener((observable,oldValue,newValue) -> selectInOtherTree(newValue, leftTree, rightTree));
        leftTree.getSelectionModel().selectedItemProperty().addListener((observable,oldValue,newValue) -> selectInOtherTree(newValue, rightTree,leftTree));
        //Add the TreeViews to the HBox
        treeBox.getChildren().add(leftTree);
        treeBox.getChildren().add(rightTree);        
        //Add the labels to the VBox
        labelBox.getChildren().add(leftTreeLabel);
        labelBox.getChildren().add(rightTreeLabel);        
        //Add the HBox and VBox to another HBox to 
        //position the layout panes
        controlBox.getChildren().add(treeBox);
        controlBox.getChildren().add(labelBox);        
        //Add the main HBOX layout pane to the scene
        Scene scene = new Scene(controlBox, 800, 250);
        Platform.setImplicitExit(false);
        Thread backGroundThread = new Thread(() -> {
                try {
                    Thread.sleep(5000);
                    System.out.println("Select left Viscount Severn");
                    leftTree.getRoot().setExpanded(true);
                    leftTree.getRoot().getChildren().get(1).setExpanded(true);
                    leftTree.getRoot().getChildren().get(2).setExpanded(true);
                    leftTree.getRoot().getChildren().get(3).setExpanded(true);
                    TreeItemString toSearch = new TreeItemString("Prince Edward - Sophie");
                    System.out.println("true:false for : " + toSearch);
                    System.out.println("true:false : " + leftTree.getRoot().getChildren().contains(toSearch));
                    System.out.println("indexOf: " + leftTree.getRoot().getChildren().indexOf(toSearch));
                    System.out.println("get: " + leftTree.getRoot().getChildren().get(leftTree.getRoot().getChildren().indexOf(toSearch)));
                    System.out.println("getRow: " + leftTree.getRow(leftTree.getRoot().getChildren().get(leftTree.getRoot().getChildren().indexOf(toSearch))));
                    leftTree.getSelectionModel().select(new TreeItemString("Princess Anne - Mark Phillips"));
                    Thread.sleep(5000);
                    System.out.println("Select right Princess Beatrice");
                    rightTree.getSelectionModel().select(new TreeItemString("Princess Beatrice"));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
       });  
        backGroundThread.setDaemon(true);
        backGroundThread.start();
        //Show the form
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}
包应用;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeView;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
公共类主扩展应用程序{
public void选择其他树(TreeItem to select,TreeView otherTree,TreeView this tree){
System.out.println(“其他树:+toSelect”);
System.out.println(“Me:+thisTree.getRow(toSelect));
System.out.println(“其他:+otherTree.getRow(toSelect));
otherTree.getSelectionModel().select(toSelect);
}   
public TreeItemString newRoot(树视图树、标签标签、字符串标签前缀){
//为树视图的层次结构创建树项
TreeItemString royalRoot=新的TreeItemString(“伊丽莎白女王-菲利普亲王”);
TreeItemString查理=新的TreeItemString(“查尔斯王子-戴安娜王妃”);
TreeItemString Annie=新的TreeItemString(“安妮公主-马克·菲利普斯”);
TreeItemString Andy=新的TreeItemString(“安德鲁王子-莎拉·弗格森”);
TreeItemString Eddie=新的TreeItemString(“爱德华王子-索菲”);
//将要用作根的TreeItem与其他TreeItem一起填充
royalRoot.getChildren().addAll(查理、安妮、安迪、埃迪);
//用更多树项填充其他树项
//建立家谱
Charlie.getChildren().addAll(
新的TreeItemString(“威廉王子”),
新的TreeItemString(“亨利王子”);
Annie.getChildren().addAll(
新的TreeItemString(“Peter Phillips”),
新的TreeItemString(“Zara Phillips”);
Andy.getChildren().addAll(
新的TreeItemString(“比阿特丽斯公主”),
新的TreeItemString(“尤金妮公主”);
Eddie.getChildren().addAll(
新的TreeItemString(“Louise女士”),
新的TreeItemString(“塞文子爵”);
返回根;
}   
@凌驾
公共无效开始(阶段初始阶段){
最后一个字符串leftTreeLabelPrefix=“从左树中选择的树项:\n”;
最后一个字符串rightTreeLabelPrefix=“从右树中选择的树项:\n”;
//使用HBOX和VBOX布局窗格隔开控件
//一排
HBox treeBox=新的HBox();
VBox labelBox=新的VBox(30);
HBox控制盒=新的HBox(10);
//创建标签以高亮显示树视图中的选定项目
最终标签leftTreeLabel=新标签(leftTreeLabel前缀);
最终标签rightTreeLabel=新标签(rightTreeLabel前缀);
//创建并清空TreeView
TreeView leftTree=new TreeView();
//使用setRoot m