JavaFX 8 : Missing caret in switch-editable ComboBox

标签 java combobox javafx-8 textfield caret

将应用程序从 JavaFX 2.2 移植到 JavaFX 8 后,可编辑组合框的插入符号丢失。在选择项目时,组合框应切换为可编辑状态。 我在 Windows 8.1 下使用 Oracle JDK 1.8 Update 102 和 Update 112 对其进行了测试。

当 ComboBox 失去焦点并重新获得焦点时,插入符号可见。

将 lambda 更改为接口(interface)实现并删除 Platform.runLater 后,它实际上可以在 JavaFX 2.2 上运行。

我包含了一个 SSCCE 来进行测试:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TestEditableComboBox extends Application{

   @Override
   public void start(Stage primaryStage) throws Exception{

      ComboBox<String> comboBox = new ComboBox<String>(FXCollections.observableArrayList("item 1",
                                                                                         "item 2",
                                                                                         "editable"));
      comboBox.setMinWidth(100D);
      comboBox.setMaxWidth(100D);
      comboBox.valueProperty().addListener((observable,
                                            oldValue,
                                            newValue) -> {

         if (newValue != null){
            if ("editable".equals(newValue)){
               // JavaFX 2.2: comboBox.setEditable(true);
               Platform.runLater(() -> comboBox.setEditable(true));
            }
            else{
               // JavaFX 2.2: comboBox.setEditable(true);
               Platform.runLater(() -> {
                  comboBox.setEditable(false);
                  comboBox.getSelectionModel().select(newValue);
               });
            }
         }
      });

      VBox vBox = new VBox(new Label("Broken caret"),
                           comboBox);
      Scene scene = new Scene(vBox);
      primaryStage.setScene(scene);
      primaryStage.show();
   }

   public static void main(String[] args){

      Application.launch(args);
   }
}

有人有解决这个问题的想法吗?或者这是一个 JavaFX 8 回归错误?

PS:如果没有 Platform.runLater,ComboBox 会抛出 java.lang.IndexOutOfBoundsException,因为它的模型在另一个修改正在进行时被修改。

最佳答案

我找到了解决此问题的方法。

com.sun.javafx.scene.control.skin.ComboBoxPopupControl中ComboBox的内部实现有一个专门的类叫做 FakeFocusTextField延伸javafx.scene.control.TextField 。调用 ComboBox::getEditor 时会返回此类的实例。 .

令人惊讶的是FakeFocusTextField类有一个名为 setFakeFocus 的公共(public)方法这将焦点集中到文本字段。 requestFocus此类中的方法将焦点赋予其父级。

解决方法是更改​​将组合框设置为可编辑的代码行:

Platform.runLater(() -> comboBox.setEditable(true));

Platform.runLater(() -> {
    comboBox.setEditable(true);
    if (this.getEditor() instanceof FakeFocusTextField){
       ((FakeFocusTextField) this.getEditor()).setFakeFocus(true);
    }
}

不幸的是,此解决方法使用 JavaFX 8 API 之外的 JavaFX 类。如果实现发生更改,它可能会中断,并且可能无法在未来的版本(如 Java 9)中工作。

关于JavaFX 8 : Missing caret in switch-editable ComboBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40239400/

相关文章:

C# WinForms ComboBox - 仅从对象中选择值

java - 在 TableView JavaFx 中动态添加新元素

Java.awt.SystemTray 不能正确显示托盘图标

如果抛出异常,Java 继续执行循环

java - 如何在DataTables中使用JSP/表达式语言显示数据?

javascript - Ext 4 ComboBox自定义触发器

c# - 从绑定(bind)到数据集的组合框中删除重复项

java - 我如何在 Java 中比较字符串?

JavaFx : bring stage to focus on keypress

tableview - 如何防止 TableView 在 javaFX 8 中对 TableColumn 进行重新排序?