JavaFX 8:在可开关编辑的ComboBox中缺少插入符号 [英] JavaFX 8: Missing caret in switch-editable ComboBox

查看:60
本文介绍了JavaFX 8:在可开关编辑的ComboBox中缺少插入符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

在将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;

公共类TestEditableComboBox扩展了应用程序{

@Override
public void start(Stage primaryStage)引发异常{

ComboBox< String> comboBox =新的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);
场景=新场景(vBox);
primaryStage.setScene(scene);
primaryStage.show();
}

public static void main(String [] args){

Application.launch(args);
}
}

任何人都有解决此问题的想法吗?还是这是JavaFX 8回归错误?



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

解决方案

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



ComboBox在类 com.sun.javafx.scene.control.skin.ComboBoxPopupControl 的内部实现中名为 FakeFocusTextField 的特殊类,它扩展了 javafx.scene.control.TextField 。调用 ComboBox :: getEditor 时,会返回此类的实例。



令人惊讶的是, FakeFocusTextField 类有一个名为 setFakeFocus 的公共方法,该方法将焦点放在文本字段上。此类中的 requestFocus 方法将焦点放在其父级。



解决方法是更改​​代码行设置comboBox可编辑为:

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

  Platform.runLater(()-> {
comboBox.setEditable(true);
if(this.getEditor()FakeFocusTextField的实例){
((FakeFocusTextField)this。 getEditor())。setFakeFocus(true);
}
}

此变通办法使用JavaFX 8 API之外的JavaFX类。如果更改实现,则可能会中断,并且可能无法在将来的版本(如Java 9)中使用。


The caret of an editable ComboBox is missing after porting an application from JavaFX 2.2 to JavaFX 8. The ComboBox should be switched to editable on selecting an item. I tested it under Windows 8.1 with Oracle JDK 1.8 Update 102 and Update 112.

When the ComboBox lost focus and regained focus, the caret is visible.

It actually works on JavaFX 2.2 after changing the lambda to an interface implementation and removing the Platform.runLater.

I included a SSCCE for testing:

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);
   }
}

Anyone have an idea to work this around? Or is this a JavaFX 8 regression bug?

PS: Without the Platform.runLater the ComboBox throws a java.lang.IndexOutOfBoundsException because its model is modified while another modification is in progress.

解决方案

I found a workaround for this issue.

The internal implementation of ComboBox at class com.sun.javafx.scene.control.skin.ComboBoxPopupControl have an specialized class called FakeFocusTextField which extends javafx.scene.control.TextField. An instance of this class is given back when calling ComboBox::getEditor.

Surprisingly the FakeFocusTextField class have a public method called setFakeFocus which gives the focus to the text field. The requestFocus method in this class gives the focus to its parent.

The workaround is to change the line of code which sets the comboBox editable from:

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

to

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

Unfortunately this workaround uses JavaFX classes outside of the JavaFX 8 API. It may break if the implementation is changed and might not work on future releases (like Java 9).

这篇关于JavaFX 8:在可开关编辑的ComboBox中缺少插入符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆