编辑:我包括示例文件,给我错误
我试图实现一个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" />