删除并重新添加后,JavaFX ComboBox 变得不可点击
JavaFX ComboBox becomes unclickable after removal and re-adding
我想我可能在 Java 中发现了一个错误,或者我做错了什么。
我根据收到的一些数据填充了一个容器。容器有一个或多个组合框。在 ComboBox 选择更改时,我收到新数据。然后我清除 GridPane 并重新添加节点(仍然存在于新数据中,and/or 添加新节点)。
ComboBox 仍然有焦点,但我无法在单击时再次激活它。任何导致 ComboBox 失去焦点的事情(例如聚焦另一个组件)都会导致它再次工作。
这是一个简化的例子。尝试使用 jdk1.8.0_162 和 jdk-9.0.4
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ComboBoxTest extends Application {
public static void main(String[] args) {
ComboBoxTest.launch(args);
}
@Override
public void start(Stage stage) {
VBox root = new VBox();
final ComboBox<String> choices = new ComboBox<>();
choices.getItems().add("Test1");
choices.getItems().add("Test2");
root.getChildren().add(choices);
choices.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> {
root.getChildren().clear();
root.getChildren().add(choices);
});
Platform.setImplicitExit(true);
stage.setScene(new Scene(root));
stage.show();
}
}
设计是动态的。我有一个从服务器收到的值列表。这用于创建 ComboBox 并将其放置在网格上。当用户更改 ComboBox 中的选择时,它会从服务器接收到一个新的值列表。此列表可能仍包含对应于网格中现有节点的值。它们被重用而不是重新创建。
只是为了不松散原因和解决方案 posted 作为对 sillyfly 已删除答案的评论(post 你自己的,我会删除它:)
A little guess as to the underlying cause/issue - the change causes the ComboBox to disappear while its list (which is technically a different stage) is showing. My guess is that leaves it in an indefinite state where it thinks the list is still showing, but it never hides so it doesn't reset. In this case, maybe calling ComboBox::hide will also work
这个假设是正确的,因为如果您通过键盘更改选择(在这种情况下下拉列表未打开),您会看到:该组合仍然可以通过键盘和鼠标访问。所以在删除之前隐藏下拉列表确实是解决方案。
在代码中(迈克尔编辑中的简化示例)
public class ReaddFocusedCombo extends Application {
@Override
public void start(Stage stage) {
VBox root = new VBox();
final ComboBox<String> choices = new ComboBox<>();
choices.getItems().add("Test1");
choices.getItems().add("Test2");
root.getChildren().add(choices);
choices.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
// guess by sillyfly: combo gets confused if popup still open
choices.hide();
root.getChildren().clear();
root.getChildren().add(choices);
// suggested in answer: working but then the choice isn't focused
//root.requestFocus();
// doesn't work
// choices.requestFocus();
});
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
更新:在 bug parade 中稍微搜索一下,发现了 similar misbehaviour on adding a showing combo which was fixed on initial attaching to a scene, but missed the dynamic use case. Filed a new issue 后者。
我想我可能在 Java 中发现了一个错误,或者我做错了什么。
我根据收到的一些数据填充了一个容器。容器有一个或多个组合框。在 ComboBox 选择更改时,我收到新数据。然后我清除 GridPane 并重新添加节点(仍然存在于新数据中,and/or 添加新节点)。
ComboBox 仍然有焦点,但我无法在单击时再次激活它。任何导致 ComboBox 失去焦点的事情(例如聚焦另一个组件)都会导致它再次工作。
这是一个简化的例子。尝试使用 jdk1.8.0_162 和 jdk-9.0.4
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ComboBoxTest extends Application {
public static void main(String[] args) {
ComboBoxTest.launch(args);
}
@Override
public void start(Stage stage) {
VBox root = new VBox();
final ComboBox<String> choices = new ComboBox<>();
choices.getItems().add("Test1");
choices.getItems().add("Test2");
root.getChildren().add(choices);
choices.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> {
root.getChildren().clear();
root.getChildren().add(choices);
});
Platform.setImplicitExit(true);
stage.setScene(new Scene(root));
stage.show();
}
}
设计是动态的。我有一个从服务器收到的值列表。这用于创建 ComboBox 并将其放置在网格上。当用户更改 ComboBox 中的选择时,它会从服务器接收到一个新的值列表。此列表可能仍包含对应于网格中现有节点的值。它们被重用而不是重新创建。
只是为了不松散原因和解决方案 posted 作为对 sillyfly 已删除答案的评论(post 你自己的,我会删除它:)
A little guess as to the underlying cause/issue - the change causes the ComboBox to disappear while its list (which is technically a different stage) is showing. My guess is that leaves it in an indefinite state where it thinks the list is still showing, but it never hides so it doesn't reset. In this case, maybe calling ComboBox::hide will also work
这个假设是正确的,因为如果您通过键盘更改选择(在这种情况下下拉列表未打开),您会看到:该组合仍然可以通过键盘和鼠标访问。所以在删除之前隐藏下拉列表确实是解决方案。
在代码中(迈克尔编辑中的简化示例)
public class ReaddFocusedCombo extends Application {
@Override
public void start(Stage stage) {
VBox root = new VBox();
final ComboBox<String> choices = new ComboBox<>();
choices.getItems().add("Test1");
choices.getItems().add("Test2");
root.getChildren().add(choices);
choices.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
// guess by sillyfly: combo gets confused if popup still open
choices.hide();
root.getChildren().clear();
root.getChildren().add(choices);
// suggested in answer: working but then the choice isn't focused
//root.requestFocus();
// doesn't work
// choices.requestFocus();
});
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
更新:在 bug parade 中稍微搜索一下,发现了 similar misbehaviour on adding a showing combo which was fixed on initial attaching to a scene, but missed the dynamic use case. Filed a new issue 后者。