JavaFX TreeView ChangeListener 旧值始终为空
JavaFX TreeView ChangeListener old value is always null
我有一个对象树视图。我想添加一个 ChangeListener,它将在右窗格中绘制我的对象并删除旧的对象(如果存在)。但我不能那样做,因为不明显的原因,我的旧值始终为空。
这是我的听众:
treeView.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends TreeItem<Asset>> ov, TreeItem<Asset> t, TreeItem<Asset> t1) -> {
t.getValue().derepresent();
t1.getValue().represent();
});
此代码使我的应用程序能够很好地 "represent" 对象。
但是当我选择另一个项目时没有任何反应。
在切换回我的对象(我想表示的对象)后,应用创建了它的第二个实例(cause previous wasn
t 已删除)。
所以我想问一下,我该如何解决?
编辑:
这是来自我的控制器 class:
的有用代码
public class Controller implements Initializable {
@FXML
private VBox infoVBox;
@FXML
private TreeView<Asset> treeView;
private Stage stage;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
public void selectRootOnClick(ActionEvent actionEvent) {
try {
final DirectoryChooser directoryChooser = new DirectoryChooser();
final File selectedDirectory = directoryChooser.showDialog(stage);
TreeItem<Asset> treeItem = new TreeItem<>(new Asset(selectedDirectory.getAbsolutePath(), infoVBox));
createTree(treeItem);
treeItem.getChildren().sort(Comparator.comparing(t -> t.getValue().getAssetPath().toLowerCase()));
treeView.setRoot(treeItem);
treeView.setCellFactory(new Callback<>() {
public TreeCell<Asset> call(TreeView<Asset> tv) {
return new TreeCell<>() {
@Override
protected void updateItem(Asset item, boolean empty) {
super.updateItem(item, empty);
setText((empty || item == null) ? "" : item.getAssetPath());
}
};
}
});
treeView.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends TreeItem<Asset>> ov, TreeItem<Asset> t, TreeItem<Asset> t1) -> {
if (t != null) t.getValue().derepresent();
t1.getValue().represent();
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void createTree(TreeItem<Asset> rootItem) throws IOException {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(rootItem.getValue().getAssetPath()))) {
for (Path path : directoryStream) {
TreeItem<Asset> newItem;
if (!Files.isDirectory(path)) {
String extension = "";
int i = path.toString().lastIndexOf('.');
if (i > 0) extension = path.toString().substring(i + 1);
switch (extension) {
case "mp3":
newItem = new TreeItem<>(new Audio(path.toString(), infoVBox));
rootItem.getChildren().add(newItem);
break;
default:
newItem = new TreeItem<>(new Asset(path.toString(), infoVBox));
rootItem.getChildren().add(newItem);
break;
}
} else {
newItem = new TreeItem<>(new Asset(path.toString(), infoVBox));
newItem.setExpanded(true);
rootItem.getChildren().add(newItem);
createTree(newItem);
}
}
}
}
}
我有一个 classes 的层次结构。在此层次结构中,音频 class 继承资产 class。
这是资产 class:
public class Asset {
protected final String assetPath;
public String getAssetPath() {
return assetPath;
}
protected VBox parent;
public Asset() {
assetPath = "";
parent = null;
}
public Asset(String path, VBox node) {
assetPath = path;
parent = node;
}
public void represent() {}
public void derepresent() {}
}
还有我的音频Class:
public final class Audio extends Asset {
private Media media;
private MediaPlayer mediaPlayer;
private MediaControl mediaControl;
public Audio() {
super();
}
public Audio(String path, VBox parent) {
super(path, parent);
}
@Override
public void represent() {
media = new Media("file:///"+assetPath);
mediaPlayer = new MediaPlayer(media);
mediaControl = new MediaControl(mediaPlayer);
parent.getChildren().add(mediaControl);
}
@Override
public void derepresent() {
mediaControl = null;
mediaPlayer = null;
media = null;
parent.getChildren().remove(mediaControl);
}
}
我也有 MediaControl,但我想它的实现对于当前线程来说是不必要的。
您将 mediaControl
设置为 null
太早了,所以 parent.getChildren().remove(mediaControl)
基本上只是 parent.getChildren().remove(null)
,它总是抛出 NullPointerException
.
将derepresent()
更改为:
@Override
public void derepresent() {
// you can drop this null-check when you're sure that mediaControl is set
if(mediaControl != null) {
parent.getChildren().remove(mediaControl);
}
mediaControl = null;
mediaPlayer = null;
media = null;
}
我还建议删除构造函数 Audio()
,因为您可能在 derepresent()
中得到 NullPointerException
,而 parent
仍然是 null
.
我有一个对象树视图。我想添加一个 ChangeListener,它将在右窗格中绘制我的对象并删除旧的对象(如果存在)。但我不能那样做,因为不明显的原因,我的旧值始终为空。 这是我的听众:
treeView.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends TreeItem<Asset>> ov, TreeItem<Asset> t, TreeItem<Asset> t1) -> {
t.getValue().derepresent();
t1.getValue().represent();
});
此代码使我的应用程序能够很好地 "represent" 对象。
但是当我选择另一个项目时没有任何反应。
在切换回我的对象(我想表示的对象)后,应用创建了它的第二个实例(cause previous wasn
t 已删除)。
所以我想问一下,我该如何解决?
编辑: 这是来自我的控制器 class:
的有用代码public class Controller implements Initializable {
@FXML
private VBox infoVBox;
@FXML
private TreeView<Asset> treeView;
private Stage stage;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
public void selectRootOnClick(ActionEvent actionEvent) {
try {
final DirectoryChooser directoryChooser = new DirectoryChooser();
final File selectedDirectory = directoryChooser.showDialog(stage);
TreeItem<Asset> treeItem = new TreeItem<>(new Asset(selectedDirectory.getAbsolutePath(), infoVBox));
createTree(treeItem);
treeItem.getChildren().sort(Comparator.comparing(t -> t.getValue().getAssetPath().toLowerCase()));
treeView.setRoot(treeItem);
treeView.setCellFactory(new Callback<>() {
public TreeCell<Asset> call(TreeView<Asset> tv) {
return new TreeCell<>() {
@Override
protected void updateItem(Asset item, boolean empty) {
super.updateItem(item, empty);
setText((empty || item == null) ? "" : item.getAssetPath());
}
};
}
});
treeView.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends TreeItem<Asset>> ov, TreeItem<Asset> t, TreeItem<Asset> t1) -> {
if (t != null) t.getValue().derepresent();
t1.getValue().represent();
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void createTree(TreeItem<Asset> rootItem) throws IOException {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(rootItem.getValue().getAssetPath()))) {
for (Path path : directoryStream) {
TreeItem<Asset> newItem;
if (!Files.isDirectory(path)) {
String extension = "";
int i = path.toString().lastIndexOf('.');
if (i > 0) extension = path.toString().substring(i + 1);
switch (extension) {
case "mp3":
newItem = new TreeItem<>(new Audio(path.toString(), infoVBox));
rootItem.getChildren().add(newItem);
break;
default:
newItem = new TreeItem<>(new Asset(path.toString(), infoVBox));
rootItem.getChildren().add(newItem);
break;
}
} else {
newItem = new TreeItem<>(new Asset(path.toString(), infoVBox));
newItem.setExpanded(true);
rootItem.getChildren().add(newItem);
createTree(newItem);
}
}
}
}
}
我有一个 classes 的层次结构。在此层次结构中,音频 class 继承资产 class。 这是资产 class:
public class Asset {
protected final String assetPath;
public String getAssetPath() {
return assetPath;
}
protected VBox parent;
public Asset() {
assetPath = "";
parent = null;
}
public Asset(String path, VBox node) {
assetPath = path;
parent = node;
}
public void represent() {}
public void derepresent() {}
}
还有我的音频Class:
public final class Audio extends Asset {
private Media media;
private MediaPlayer mediaPlayer;
private MediaControl mediaControl;
public Audio() {
super();
}
public Audio(String path, VBox parent) {
super(path, parent);
}
@Override
public void represent() {
media = new Media("file:///"+assetPath);
mediaPlayer = new MediaPlayer(media);
mediaControl = new MediaControl(mediaPlayer);
parent.getChildren().add(mediaControl);
}
@Override
public void derepresent() {
mediaControl = null;
mediaPlayer = null;
media = null;
parent.getChildren().remove(mediaControl);
}
}
我也有 MediaControl,但我想它的实现对于当前线程来说是不必要的。
您将 mediaControl
设置为 null
太早了,所以 parent.getChildren().remove(mediaControl)
基本上只是 parent.getChildren().remove(null)
,它总是抛出 NullPointerException
.
将derepresent()
更改为:
@Override
public void derepresent() {
// you can drop this null-check when you're sure that mediaControl is set
if(mediaControl != null) {
parent.getChildren().remove(mediaControl);
}
mediaControl = null;
mediaPlayer = null;
media = null;
}
我还建议删除构造函数 Audio()
,因为您可能在 derepresent()
中得到 NullPointerException
,而 parent
仍然是 null
.