selectedItem.valueProperty().set(new Person(selectedPerson.getName(), selectedPerson.getAge()));
我认为这个解决方案是非常愚蠢的,必须有一个方法如何编码它更好。我不能每次都创建一个新的Person实例,这对我来说是不可接受的。
我也尝试为treeView触发一个事件,但这种方法会破坏焦点,也是一个愚蠢的解决方案。我也找到了这样的解决办法:
treeView.getRoot().getChildren().set(treeView.getSelectionModel().getSelectedIndex(), new TreeItem<MainAppTF.Person>(updatedPerson));
这也是不好的解决办法。
public class MainAppTF extends Application {
private TreeView<Person> treeView;
private final TreeItem<Person> rootNode = new TreeItem<Person>(new Person("Root", 0));
private TextField textField;
@Override
public void start(Stage stage) {
VBox box = new VBox();
Scene scene = new Scene(box, 400, 400);
treeView = new TreeView<Person>(rootNode);
treeView.setShowRoot(false);
rootNode.setExpanded(true);
List<TreeItem<Person>> list = new ArrayList<>();
list.add(new TreeItem<Person>(new Person("Adam", 20)));
list.add(new TreeItem<Person>(new Person("Eva", 19)));
list.add(new TreeItem<Person>(new Person("Carl", 30)));
rootNode.getChildren().setAll(list);
textField = new TextField("");
attachListeners();
box.getChildren().add(treeView);
box.getChildren().add(textField);
VBox.setMargin(treeView, new Insets(10));
VBox.setMargin(textField, new Insets(10));
stage.setScene(scene);
stage.show();
}
private void attachListeners() {
treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<Person>>() {
@Override
public void changed(ObservableValue<? extends TreeItem<Person>> observable, TreeItem<Person> oldValue, TreeItem<Person> newValue) {
textField.setText(newValue.getValue().getName());
}
});
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (!newValue) {
updateTreeViewItem();
}
}
});
textField.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
updateTreeViewItem();
}
});
}
private void updateTreeViewItem() {
TreeItem<Person> selectedItem = treeView.getSelectionModel().getSelectedItem();
Person selectedPerson = selectedItem.getValue();
selectedPerson.nameProperty().set(textField.getText());
// FIXME This is silly! There must be another way!
selectedItem.valueProperty().set(new Person(selectedPerson.getName(), selectedPerson.getAge()));
}
public static void main(String[] args) {
Application.launch(args);
}
private class Person {
private StringProperty name;
private int age;
public Person() {
this(null, 0);
}
public Person(String name, int age) {
this.name = new SimpleStringProperty(name);
this.age = age;
}
public StringProperty nameProperty() {
return name;
}
public String getName() {
return name.getValue();
}
public void setName(String name) {
this.name.setValue(name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return getName() + " - " + getAge();
}
}
}
当TreeItem
包装的人员
的名称更改时,您希望TreeModificationEvent
接收TreeModificationEvent。
可以通过将侦听器附加到person的
nameProperty()
来实现这一点,然后触发适当的事件:
TreeItem<Person> treeItem = new TreeItem<>(person);
ChangeListener<String> nameListener = (obs, oldName, newName) -> {
TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem);
Event.fireEvent(treeItem, event);
};
person.nameProperty().addListener(nameListener);
如果有可能更改
TreeItem
(TreeItem.setValue(new Person(...))
)包装的值,那么您需要确保从旧的Person中删除监听器并将其添加到新的Person中。因此,谨慎的做法可能是:
treeItem.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue != null) {
oldValue.nameProperty().removeListener(nameListener);
}
if (newValue != null) {
newValue.nameProperty().addListener(nameListener);
}
});
private TreeItem<Person> createTreeItem(Person person) {
TreeItem<Person> treeItem = new TreeItem<>(person);
ChangeListener<String> nameListener = (obs, oldName, newName) -> {
TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem);
Event.fireEvent(treeItem, event);
};
person.nameProperty().addListener(nameListener);
treeItem.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue != null) {
oldValue.nameProperty().removeListener(nameListener);
}
if (newValue != null) {
newValue.nameProperty().addListener(nameListener);
}
});
return treeItem ;
}
然后做
list.add(createTreeItem(new Person("Adam", 20)));
list.add(createTreeItem(new Person("Eva", 19)));
list.add(createTreeItem(new Person("Carl", 30)));
也可以创建
TreeItem
的子类:
private class PersonTreeItem extends TreeItem<Person> {
private ChangeListener<String> nameListener = (obs, oldName, newName) -> {
TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), this);
Event.fireEvent(this, event);
};
public PersonTreeItem(Person person) {
super(person);
person.nameProperty().addListener(nameListener);
this.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue != null) {
oldValue.nameProperty().removeListener(nameListener);
}
if (newValue != null) {
newValue.nameProperty().addListener(nameListener);
}
});
}
}
并且做
list.add(new PersonTreeItem(new Person("Adam", 20)));
list.add(new PersonTreeItem(new Person("Eva", 19)));
list.add(new PersonTreeItem(new Person("Carl", 30)));
import java.util.ArrayList;
import java.util.List;
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.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeItem.TreeModificationEvent;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MainAppTF extends Application {
private TreeView<Person> treeView;
private final TreeItem<Person> rootNode = new TreeItem<Person>(new Person("Root", 0));
private TextField textField;
@Override
public void start(Stage stage) {
VBox box = new VBox();
Scene scene = new Scene(box, 400, 400);
treeView = new TreeView<Person>(rootNode);
treeView.setShowRoot(false);
rootNode.setExpanded(true);
List<TreeItem<Person>> list = new ArrayList<>();
list.add(createTreeItem(new Person("Adam", 20)));
list.add(createTreeItem(new Person("Eva", 19)));
list.add(createTreeItem(new Person("Carl", 30)));
rootNode.getChildren().setAll(list);
textField = new TextField("");
attachListeners();
box.getChildren().add(treeView);
box.getChildren().add(textField);
VBox.setMargin(treeView, new Insets(10));
VBox.setMargin(textField, new Insets(10));
stage.setScene(scene);
stage.show();
}
private void attachListeners() {
treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<Person>>() {
@Override
public void changed(ObservableValue<? extends TreeItem<Person>> observable, TreeItem<Person> oldValue, TreeItem<Person> newValue) {
textField.setText(newValue.getValue().getName());
}
});
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (!newValue) {
updateTreeViewItem();
}
}
});
textField.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
updateTreeViewItem();
}
});
}
private void updateTreeViewItem() {
TreeItem<Person> selectedItem = treeView.getSelectionModel().getSelectedItem();
Person selectedPerson = selectedItem.getValue();
selectedPerson.nameProperty().set(textField.getText());
// FIXME This is silly! There must be another way!
// selectedItem.valueProperty().set(new Person(selectedPerson.getName(), selectedPerson.getAge()));
}
public static void main(String[] args) {
Application.launch(args);
}
private TreeItem<Person> createTreeItem(Person person) {
TreeItem<Person> treeItem = new TreeItem<>(person);
ChangeListener<String> nameListener = (obs, oldName, newName) -> {
TreeModificationEvent<Person> event = new TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem);
Event.fireEvent(treeItem, event);
};
person.nameProperty().addListener(nameListener);
treeItem.valueProperty().addListener((obs, oldValue, newValue) -> {
if (oldValue != null) {
oldValue.nameProperty().removeListener(nameListener);
}
if (newValue != null) {
newValue.nameProperty().addListener(nameListener);
}
});
return treeItem ;
}
private class Person {
private StringProperty name;
private int age;
public Person() {
this(null, 0);
}
public Person(String name, int age) {
this.name = new SimpleStringProperty(name);
this.age = age;
}
public StringProperty nameProperty() {
return name;
}
public String getName() {
return name.getValue();
}
public void setName(String name) {
this.name.setValue(name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return getName() + " - " + getAge();
}
}
}
我有1个“viewelements”-类,1个控制器和1个fxml-文件。 ViewElements-Class包含FXML的元素,如按钮和文本字段。Controller-Class包含业务逻辑。 我试图更新文本字段“TextFieldDateIausWaeHlen”,我想将文件的路径设置到文本字段中,但我的方法不起作用。 我的错误在哪里?
我有一个目标,它有一个目标清单。一个目标有一系列的策略。一个战略有一个战术清单。战术有一个任务列表。 我希望能够在树视图中显示这一点,我希望树与项目同步。也就是说,如果我删除一个目标,该目标及其子目标也将从TreeView中消失。 计划是创建一个包装PlanItem的TreeItem。然后,将TreeItem的子TreeItems与PlanItem的子PlanItems同步。对于每个嵌套的Plan
我已经扩展了TreeCell和TreeItem类。MyTreeItem包含一个自定义属性,我在MyTreeCell中使用它来渲染图形/字体等。问题是当我设置MyTreeCell.custom属性我不知道如何使TreeView/单元格重绘。 例如: 任何关于解决方案或(缺乏)设计方法的意见都受到赞赏。
在选择我的treeview时遇到问题。其思想是,用户单击该项,然后将数据添加到他们选择的节点下 似乎所选项目是一个文本块,我似乎找不到一种方法将其作为treeview项目来添加节点。 是的,我对这种编程很陌生。 感谢您提供的任何帮助。
树细胞是定制的,它看起来像下图。 在右侧,我选择了一棵树单元格或树项目。正如您所看到的,每个单元格的左侧都有手的图像视图。默认情况下,它是黑色的,但我想用白色图标替换它。如上所述。 我希望所有的文本和图像视图图标在选择改变为白色。和最后选择的树单元格回到正常的黑色。 我的树细胞代码如下。 问题是正确选择并添加了新的白色图标,但如何将上一个选定树项目的图像视图改回黑色图标。实际上,我有两张相同类型的
Treeview小部件显示实现gtk.TreeModel接口的模型的内容。 PyGTK提供以下类型的模型 - gtk.ListStore gtk.TreeStore gtk.TreeModelSort ListStore是一个列表模型。 与gtk.TreeView小部件关联时,它会生成一个包含要从中选择的项的列表框。 使用以下语法声明gtk.ListStore对象 - store = gtk.Li