我试图在onMouseClick事件期间获取TreeItems valueProperty.我有一个以下类型的TreeView:
@FXML private TreeView<Pair<URIImpl,String>> myTreeview;
FXML如下:
<TreeView fx:id="myTreeview" onMouseClicked="#myTreeview_Clicked" prefHeight="551.0" prefWidth="166.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
我想在点击时取回我的模型(配对实例).
void myTreeview_Clicked(MouseEvent event) { if(event.getTarget() instanceof ...) { // Fetch Target } }
在我的案例中,目标对象是Label文本,据我所知,它不包含封装的模型引用.有人可以建议吗?这似乎是一个非常基本的特征.单向绑定……带有某种参考.我不打算编辑TreeItems.
这个帖子似乎与问题类似:
Model-Identifier for Node in JavaFX 2 TreeItem
谢谢
解决方法
关键是在TreeView上定义一个
cell factory,在单元工厂中将鼠标单击事件处理程序添加到树单元格中.如此定义的鼠标单击事件处理程序将具有对支持树单元格的模型对象的完全访问权限,并且可以使用它执行所需的操作.
在下面的示例中,当用户单击树中的单元格时,单击处理程序从与所单击的单元格相关的基础模型项目中提取信息,并将该信息呈现到树下的标签中.
TreeApplication.java
import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.*; import javafx.stage.*; public class TreeApplication extends Application { @Override public void start(final Stage stage) throws Exception { final FXMLLoader loader = new FXMLLoader( getClass().getResource("treeInterface.fxml") ); final Parent root = (Parent) loader.load(); stage.setScene(new Scene(root)); stage.show(); } public static void main(String[] args) { launch(args); } }
TreeController.java
import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.util.Callback; import javafx.util.Pair; import java.net.URL; import java.util.ResourceBundle; public class TreeController implements Initializable { @FXML private TreeView<Pair<URIImpl,String>> treeView; @FXML private Label clickedPair; @Override public void initialize(URL location,ResourceBundle resources) { treeView.setCellFactory(new Callback<TreeView<Pair<URIImpl,String>>,TreeCell<Pair<URIImpl,String>>>() { @Override public TreeCell<Pair<URIImpl,String>> call(TreeView<Pair<URIImpl,String>> treeView) { return new TreeCell<Pair<URIImpl,String>>() { final ImageView iconView = new ImageView(); @Override protected void updateItem(final Pair<URIImpl,String> pair,boolean empty) { super.updateItem(pair,empty); if (!empty && pair != null) { setText( pair.getValue() ); setGraphic( iconView ); iconView.setImage(pair.getKey().getImage()); } else { setText(null); setGraphic(null); } setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { clickedPair.setText( "Key: " + pair.getKey() + " Value: " + pair.getValue() ); } }); } }; } }); loadTreeItems( createPair("http://www.google.com","google.com","Google"),createPair("http://www.microsoft.com","microsoft.com","Microsoft"),createPair("http://www.yahoo.com","yahoo.com","Yahoo") ); } private Pair<URIImpl,String> createPair(String uri,String domain,String name) { return new Pair<>(new URIImpl(uri,domain),name); } private void loadTreeItems(Pair<URIImpl,String>... rootItems) { TreeItem<Pair<URIImpl,String>> root = new TreeItem(createPair("N/A","","Root Node")); root.setExpanded(true); for (Pair<URIImpl,String> pair: rootItems) { root.getChildren().add( new TreeItem<>( pair ) ); } treeView.setRoot(root); } }
URIImpl.java
import javafx.scene.image.Image; class URIImpl { private final String uri; private final String domain; private Image image; public URIImpl(String uri,String domain) { this.uri = uri; this.domain = domain; } public String getUri() { return uri; } public String getDomain() { return domain; } public Image getImage() { if (image == null) { image = new Image("https://plus.google.com/_/favicon?domain=" + getDomain()); } return image; } @Override public String toString() { return "URIImpl{" + "uri->" + uri + '}'; } }
treeInterface.fxml
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns:fx="http://javafx.com/fxml" fx:controller="tests.treesample.TreeController"> <TreeView fx:id="treeView" layoutX="0" layoutY="0" prefHeight="193.0" prefWidth="471.0" /> <Label fx:id="clickedPair" layoutX="0" layoutY="200"/> </AnchorPane>
更新
This worked just fine. However,the icon image seems to be lost once we setup the CallBack event handlers.
是的,看起来如果你创建自己的单元工厂,你还需要在单元工厂内手动设置图形.这是因为默认树项单元工厂将从树项中获取图形,如果已在树项上设置了图形,则此逻辑将不会出现在自定义单元工厂中,除非您在那里进行编码.
我更新了示例解决方案中的代码,以显示如何在自定义单元工厂生成的树单元格上设置图形.更新后的代码从支持树单元格的模型中获取图形图像,但是如果首选,则可以从树项目的图形属性中检索它.要从TreeItem获取图形,请使用blacks0ul建议的以下代码:
TreeItem<Pair<URIImpl,String>> item = getTreeItem(); if (item != null && item.getGraphic() != null) { setGraphic(item.getGraphic()); }