编辑:我包括示例文件,给我错误
我试图实现一个ComboBox,它根据here中的配方根据KeyStrokes过滤项目。我想列出世界各国

我正在使用FilterComboBox.fxml

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

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import persondetails2.controller.*?>

<fx:root type="javafx.scene.control.ComboBox" fx:id="countries"
         xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2"
         fx:controller="persondetails2.controller.FilterComboBox">
        <items>
          <FXCollections fx:factory="observableArrayList">
            <String fx:value="Austria" />
            <String fx:value="Denmark" />
            <String fx:value="France" />
            <String fx:value="Germany" />
            <String fx:value="Italy" />
            <String fx:value="Portugal" />
            <String fx:value="Spain" />
          </FXCollections>
        </items>
</fx:root>


如配方中的FilterComboBox.java。来源如下:

    /*
 * Follows: https://stackoverflow.com/questions/13362607/combobox-jump-to-typed-char
 */

package persondetails2.controller;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

/**
 *
 * @author DRY
 */
public class FilterComboBox<T> extends ComboBox<T> {
//implements Initializable{
    private final FilterComboBox<T> fcbo = this;

    private ObservableList<T> items;
    private ObservableList<T> filter;
    private String s;
    private Object selection;

    private class KeyHandler implements EventHandler<KeyEvent> {

        private SingleSelectionModel<T> sm;

        public KeyHandler() {
            sm = getSelectionModel();
            s = "";
            System.err.println("Initialized keyhandler");
        }

        @Override
        public void handle(KeyEvent event) {
            filter.clear();
            // handle non alphanumeric keys like backspace, delete etc
            if (event.getCode() == KeyCode.BACK_SPACE && s.length() > 0) {
                s = s.substring(0, s.length() - 1);
            } else {
                s += event.getText();
            }

            if (s.length() == 0) {
                fcbo.setItems(items);
                sm.selectFirst();
                return;
            }
            //System.out.println(s);
            if (event.getCode().isLetterKey()) {
                for (T item : items) {
                    if (item.toString().toUpperCase().startsWith(s.toUpperCase())) {

                        filter.add(item);
                        System.out.println(item);

                        fcbo.setItems(filter);

                        //sm.clearSelection();
                        //sm.select(item);

                    }
                }
                sm.select(0);
            }

        }
    }

    public FilterComboBox(final ObservableList<T> items) {
        super(items);
        this.items = items;
        this.filter = FXCollections.observableArrayList();

        setOnKeyReleased(new KeyHandler());

        this.focusedProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if ((boolean)newValue == false) {
                    s = "";
                    fcbo.setItems(items);
                    fcbo.getSelectionModel().select((T)selection);
                }

            }

        });

        this.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if (newValue != null) {
                    selection = (Object) newValue;
                }

            }
        });
    }

}


我的主视图称为PersonDetails.fxml

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


<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>


<AnchorPane xmlns:fx="http://javafx.com/fxml/1" id="AnchorPane" prefHeight="200" prefWidth="320" fx:controller="persondetails2.controller.PersonDetailsController">
  <ScrollPane id="personalData" fx:id="personaldata" fitToHeight="false" focusTraversable="false" maxHeight="-Infinity" prefHeight="-1.0" prefViewportHeight="1440.0" prefWidth="569.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="-2.0">
    <content>
      <AnchorPane id="Content" focusTraversable="false" maxWidth="-1.0" minHeight="0.0" minWidth="0.0" prefHeight="-1.0" prefWidth="600.0">
        <children>
          <VBox focusTraversable="false" prefHeight="-1.0" prefWidth="-1.0" spacing="2.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
            <children>
              <Label prefHeight="21.0001220703125" text="Personal Details">
                <font>
                  <Font name="System Bold" size="14.0" fx:id="x1" />
                </font>
              </Label>

              <GridPane id="GridPane" focusTraversable="false" hgap="3.0" prefWidth="354.0" vgap="4.0">
                <children>
                  <Label text="Name:" GridPane.columnIndex="0" GridPane.rowIndex="0">
                    <labelFor>
                      <TextField fx:id="name" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="0" />
                    </labelFor>
                  </Label>
                  <fx:reference source="name" />
                  <Label text="Surname:" GridPane.columnIndex="0" GridPane.rowIndex="1" />
                  <TextField fx:id="surname" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                  <Label text="Country:" GridPane.columnIndex="0" GridPane.rowIndex="2"  />
                  <fx:include source="FilterComboBox.fxml" GridPane.columnIndex="1" GridPane.rowIndex="2" />
                </children>
              </GridPane>
            </children>
            <padding>
              <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
            </padding>
          </VBox>
        </children>
        <padding>
          <Insets left="5.0" right="5.0" />
        </padding>
      </AnchorPane>
    </content>
  </ScrollPane>
</AnchorPane>


各自的控制器是PersonDetailsController.java

package persondetails2.controller;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

/**
 *
 * @author DRY
 */
public class PersonDetailsController implements Initializable {

    @FXML
    private Label label;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
        label.setText("Hello World!");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }

}


现在,此配置为我提供了一个java.lang.InstantiationException: persondetails2.controller.FilterComboBox。我想读取控制器初始化中的数据,然后能够设置TextFields中的值以及ComboBox中的选定值。

关于如何继续的任何想法?

最佳答案

由于您是在FXML文件中设置组合框的项目,因此我将FilterComboBox构造函数重构为无参数,并添加了加载FXML文件的代码:

public class FilterComboBox<T> extends ComboBox<T> {

    private final ObservableList<T> items;
    private final ObservableList<T> filter;
    private String s;
    private Object selection;

    private class KeyHandler implements EventHandler<KeyEvent> {

        private SingleSelectionModel<T> sm;

        public KeyHandler() {
            sm = getSelectionModel();
            s = "";
            System.err.println("Initialized keyhandler");
        }

        @Override
        public void handle(KeyEvent event) {
            filter.clear();
            // handle non alphanumeric keys like backspace, delete etc
            if (event.getCode() == KeyCode.BACK_SPACE && s.length() > 0) {
                s = s.substring(0, s.length() - 1);
            } else {
                s += event.getText();
            }

            if (s.length() == 0) {
                setItems(items);
                sm.selectFirst();
                return;
            }
            //System.out.println(s);
            if (event.getCode().isLetterKey()) {
                for (T item : items) {
                    if (item.toString().toUpperCase().startsWith(s.toUpperCase())) {

                        filter.add(item);
                        System.out.println(item);

                        setItems(filter);

                        //sm.clearSelection();
                        //sm.select(item);
                    }
                }
                sm.select(0);
            }

        }
    }

    public FilterComboBox() {

        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FilterComboBox.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }

        items = getItems();
        this.filter = FXCollections.observableArrayList();

        setOnKeyReleased(new KeyHandler());

        this.focusedProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if ((boolean) newValue == false) {
                    s = "";
                    setItems(items);
                    getSelectionModel().select((T) selection);
                }
            }
        });

        this.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                if (newValue != null) {
                    selection = (Object) newValue;
                }
            }
        });
    }

}


接下来,将FilterComboBox.fxml更改为:

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

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import persondetails2.controller.*?>

<fx:root type="FilterComboBox"
         xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
        <items>
          <FXCollections fx:factory="observableArrayList">
            <String fx:value="Austria" />
            <String fx:value="Denmark" />
            <String fx:value="France" />
            <String fx:value="Germany" />
            <String fx:value="Italy" />
            <String fx:value="Portugal" />
            <String fx:value="Spain" />
          </FXCollections>
        </items>
</fx:root>


并将PersonDetails中的fx:include替换为:

<?import persondetails2.controller.FilterComboBox ?>
...

<FilterComboBox GridPane.columnIndex="1" GridPane.rowIndex="2" />

10-08 10:56