设置自定义javafx组合框的值
编辑:我包含了一些给我带来错误的示例文件 我正在尝试实现一个组合框,它根据击键来过滤项目,遵循来自的配方。我想列出世界上的国家 我正在使用FilterComboBox.fxml设置自定义javafx组合框的值,java,javafx-2,Java,Javafx 2,编辑:我包含了一些给我带来错误的示例文件 我正在尝试实现一个组合框,它根据击键来过滤项目,遵循来自的配方。我想列出世界上的国家 我正在使用FilterComboBox.fxml <?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import javafx.collections.*?> <?import javafx.scene.*?> <?import java
<?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>
<?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>
这个配置现在为我提供了一个java.lang.InstantiationException:persondetails2.controller.FilterComboBox
。我想读取控制器初始化中的数据,然后能够设置文本字段中的值以及组合框中的所选值
关于如何继续,有什么想法吗?既然您正在FXML文件中为combobox设置项,我将FilterComboBox构造函数重构为no参数,并添加了加载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;
}
}
});
}
}
你能在加载fxml的地方显示代码吗?只是编辑了文章以反映加载方式我认为你不能将
与动态根fxml(即使用
的根fxml)一起使用:无法设置根元素。您可能只需要执行
,这假设您的过滤器ComboBox.java
设置正确。谢谢@James\u D。我尝试了创建过滤器ComboBox
控件的步骤,但是在PersonDetails.fxml
中(请参阅上文了解稍微不同的版本)我在编辑FXML时遇到一个错误,即FXML加载器无法创建实例FilterComboBox
(尽管我已经在前言中包含了这些包)。感谢@Uluk Biy,我克服了这个障碍,但现在它给了我一个错误,即它无法将FilterComboBox字段packages.countries设置为javafx.scene.control.ComboBox
。很抱歉,我没有给出更多细节,因为这是一个复杂设计的一部分,目前这给了我一个InstantiationException@YannisP. 用猜测来回答是困难的。看起来您有两个FXML文件和两个控制器文件。你能不能只发布那些可复制的格式。嗨@Uluk Biy。我已经编辑了这篇文章,包括一个可复制的例子,谢谢@扬尼斯普。否,FXMLLoader将通过反射创建FilterComboBox的实例。默认情况下(如果未使用工厂),它将不调用参数构造函数。您看到的实例化异常就是由于这个原因,即加载程序找不到arg构造函数。参数化构造函数可以在工厂中使用,或者您自己显式创建一个参数化实例,然后调用加载程序的setController。
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
}
}
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;
}
}
});
}
}
<?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>
<?import persondetails2.controller.FilterComboBox ?>
...
<FilterComboBox GridPane.columnIndex="1" GridPane.rowIndex="2" />