JavaFX 8:在可切换的ComboBox中缺少插入符号

时间:2016-10-25 11:59:42

标签: java combobox javafx-8 textfield caret

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

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

在将lambda更改为接口实现并删除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因为其模型被修改而另一个修改正在进行中。

1 个答案:

答案 0 :(得分:0)

我没有找到比火和燃料更好的策略,但是,我将在非标准API调用周围添加一些额外的防护措施。只有在JavaFX版本为8的情况下,才尝试使用“ bodge”,并带有try catch,以最大程度地减少JavaFX未来版本失败的机会。

同样有趣的是,如果将setFakeFocus称为“ bodge”到两个ComboBoxes,则它们中的两个都有可能具有选择权。我的解决方法是在应用“凸出部分”之前先以正常方式请求焦点。

这是我在Kotlin的完整解决方案:

val javaFXVersion by lazy { System.getProperties().getProperty("javafx.runtime.version") }

fun ComboBox<*>.requestFocusWithCaret() {
    requestFocus()

    if (javaFXVersion.startsWith("8.")) {
        try {
            val theEditor = editor
            if (theEditor is FakeFocusTextField) {
                theEditor.setFakeFocus(true)
            }
        } catch (e: Exception) {
        }
    }
}

然后可以使用:

myComboBox.requestFocusWithCaret()