簡體   English   中英

如何設置ComboBox編輯器事件處理程序

[英]How to set ComboBox editor event handler

我試圖在一個簡單的JavaFX應用程序中將鍵事件處理程序添加到可編輯的ComboBox中。 由於Scene Builder不提供對ComboBox中TextField的訪問,因此我必須在代碼中添加事件處理程序。

這是我添加處理程序的嘗試。

主班

package sample;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.stage.Stage;

public class Main extends Application {

    @FXML
    private ComboBox combo;

    @Override
    public void start(Stage primaryStage) throws Exception{
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Parent root = loader.load();
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 400, 300));
        primaryStage.show();

        Controller c = loader.getController();
        combo.getEditor().setOnKeyTyped(c::handleComboKeyPress);
    }


    public static void main(String[] args) {
        launch(args);
    }
}

控制器類

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyEvent;

public class Controller {
    @FXML
    private ComboBox combo;

    public void handleComboKeyPress(KeyEvent ke)
    {
        System.out.print("key press. ");  // debugging
        String query = combo.getEditor().getText();
        System.out.println(query);   // debugging
    }
}

FXML(sample.fxml)

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.Pane?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <ComboBox fx:id="combo" editable="true" layoutX="75.0" layoutY="34.0" prefWidth="150.0" promptText="City, State" visibleRowCount="5" />
   </children>
</Pane>

這會在start方法的最后一行出現空指針異常而崩潰。 問題是combo還沒有值,因為(我假設)FXML加載器在單獨的線程中運行,並且在我的代碼嘗試調用getEditor時還沒有完成。

設置事件處理程序的更合適的方法是什么?

編輯:添加了完整的源代碼

start方法需要訪問在Controller類中聲明的ComboBox變量。 僅在Main類中使用@FXML注釋ComboBox變量是@FXML的。

我通過將getComboBox方法添加到Controller類解決了該問題。 這將返回combo變量引用的ComboBox實例。

public ComboBox getComboBox()
{
    return combo;
}

在Main類中,使用此方法進入ComboBox底層的編輯器:

Controller c = loader.getController();
c.getComboBox().getEditor().setOnTyped(c::handleComboKeyPress);

這是修改后的主類:

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Parent root = loader.load();
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 400, 300));
        primaryStage.show();

        Controller c = loader.getController();
        c.getComboBox().getEditor().setOnKeyTyped(c::handleComboKeyPress);
    }

更好的解決方案

如下面的@Slaw所建議的,另一種(更好的)解決方案是在Controller中設置keyTyped處理程序。 使用initialize方法,該方法會由加載程序自動調用(如果存在)。

public void initialize()
{
    combo.getEditor().setOnKeyTyped(this::handleComboKeyPress);
}

這是整個Controller類(減去導入):

public class Controller {
    @FXML
    private ComboBox combo;

    public void handleComboKeyPress(KeyEvent ke)
    {
        // Do stuff
        System.out.println("key pressed.");
    }

    public void initialize()
    {
        combo.getEditor().setOnKeyTyped(this::handleComboKeyPress);
    }
}

另一個選擇是直接將事件處理程序掛接到fxml中。 不確定是否在所有情況下都是安全的(不是fxml gal,只是感興趣:)-但是fx:reference似乎允許訪問元素的(任意?)屬性。

以下代碼段將keyTyped的eventHandler設置為組合的編輯器:

<ComboBox fx:id="combo" editable="true" />
<fx:reference source="combo.editor" onKeyTyped="#handleTyped" /> 

這使控制器無需編寫代碼,除了處理程序方法外:

@FXML 
private ComboBox<String> combo;

@FXML 
private void handleTyped(KeyEvent ev) {
    System.out.println("ev: " + ev);
}

更新 :這似乎在fx8中不起作用(感謝Matt,要注意!)-在fx11中起作用(未測試其他任何東西)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM