我正在尝试制作一个JavaFX ComboBox
来记住用户输入的条目的历史记录。添加新项目有效,但是从下拉菜单中选择无效。
简而言之,我试图将控件
ComboBox
的第一项。TextField
部分以保留下一个条目。ComboBox
中选择一个项目后,会将选择内容复制到TextField
,而无需修改ComboBox
的项目。添加新项目效果很好,这是将先前的条目复制到该字段的过程令人沮丧。
我唯一能找到的类似问题是javafx combobox items list issue,很遗憾,该解决方案无法解决我的问题。
代码
import java.util.LinkedList;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
public class HistoryField<String> extends ComboBox<String> {
public final static int DEFAULT_MAX_ENTRIES = 256;
//Data members
private int maxSize;
private final ObservableList<String> history;
//Default constructor
public HistoryField() {
this(DEFAULT_MAX_ENTRIES, (String[]) null);
}
public HistoryField(int maxSize, String ... entries) {
super(FXCollections.observableList(new LinkedList<>()));
this.setEditable(true);
this.maxSize = maxSize;
this.history = this.getItems();
//Populate list with entries (if any)
if (entries != null) {
for (int i = 0; ((i < entries.length) && (i < this.maxSize)); i++) {
this.history.add(entries[i]);
}
}
this.valueProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
if ((oldValue == null) && (newValue != null)) {
if (this.getSelectionModel().getSelectedIndex() < 0) {
this.getItems().add(0, newValue);
this.getSelectionModel().clearSelection();
}
} else {
//This throws IndexOutOfBoundsException
this.getSelectionModel().clearSelection();
}
});
}
}
测试类
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class HistoryFieldTest extends Application {
private HistoryField<String> historyField;
@Override
public void start(Stage primaryStage) {
this.historyField = new HistoryField<>();
BorderPane root = new BorderPane();
root.setBottom(historyField);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("History Field Test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
谢谢!
答案 0 :(得分:0)
尝试以下更新的HistoryField
类。我做了几处更改。
首先,不要传递varargs
的字符串,只需传递所需的数组即可。然后,您可以使用List
方法将数组转换为ComboBox
,准备好Arrays.asList()
。
我还简化了将新项目添加到列表的过程。现在,侦听器只会将尚不存在的项目添加到列表中。
您也从未处理过max_size
的情况,因此我添加了一个简单的检查,以在达到max_size
后删除较旧的条目。
仅当将项目添加到列表时,才清除该字段;从您的问题尚不清楚这是否是所需的行为。
public class HistoryField extends ComboBox<String> {
private final static int DEFAULT_MAX_ENTRIES = 5;
//Data members
private int maxSize;
private final ObservableList<String> history;
//Default constructor
public HistoryField() {
this(DEFAULT_MAX_ENTRIES, null);
}
/* Changed parameter to an array instead of list of Strings */
public HistoryField(int maxSize, String[] entries) {
this.setEditable(true);
this.maxSize = maxSize;
/* Convert the passed array to a list and populate the dropdown */
if (entries != null) {
history = FXCollections.observableArrayList(Arrays.asList(entries));
} else {
history = FXCollections.observableArrayList();
}
setItems(history);
this.valueProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
// Check if value already exists in list
if (!this.history.contains(newValue)) {
this.history.add(0, newValue);
// If the max_size has been reached, remove the oldest item from the list
if (this.history.size() > maxSize) {
this.history.remove(history.size() - 1);
}
System.out.println(history);
// Clear the selection when new item is added
this.getSelectionModel().clearSelection();
}
}
});
}
}