具有历史功能的JavaFX可编辑ComboBox [英] JavaFX editable ComboBox with history function
问题描述
我正在尝试制作一个JavaFX ComboBox
,它会记住用户输入的条目的历史记录。添加新项目有效,但从下拉列表中选择不起作用。
I am attempting to make a JavaFX ComboBox
that remembers the history of the entries entered by the user. Adding new items works, but selecting from the drop-down does not.
简而言之,我正在尝试将控件设置为
In a nutshell, I am trying to get the control to
- 将最近输入的条目添加到顶部,作为
ComboBox
的第一项。 - 清除下一个条目的
TextField
部分。 - 从
ComboBox
,将选择复制到TextField
,而不修改ComboBox
的项目。
- Add the most recently typed entry to the top, as the first item of the
ComboBox
. - Clear the
TextField
portion for the next entry. - Upon selecting an item from the
ComboBox
, will copy selection to theTextField
, without modifying theComboBox
's items.
添加新项目工作正常,复制之前的字段条目令人沮丧。
Adding new items works fine, it's the copying a previous entry to the field is proving frustrating.
我能找到的唯一类似问题是 javafx combobox items list issue ,其解决方案很遗憾没有解决我的问题。
The only similar problem I could find was javafx combobox items list issue, whose solution unfortunately did not fix my problem.
代码
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);
}
}
谢谢!
推荐答案
尝试以下更新的 HistoryField
类。我做了一些更改。
Try the following updated HistoryField
class. There are a couple of changes I made.
首先,不要传递字符串的 varargs
,而只是传递你想要的数组。然后,您可以使用 Arrays.asList将数组转换为
方法。 List
为 ComboBox
做好准备)
First of all, instead of passing a varargs
of Strings, just pass the array you want. You can then convert the array to a List
ready for the ComboBox
using Arrays.asList()
method.
此外,我简化了向列表中添加新项目的过程。监听器现在只会在列表中添加一个项目(如果它尚不存在)。
Also, I streamlined the process of adding a new item to the list. The listener will now only add an item to the list if it doesn't already exist.
你也从未处理过 max_size
情况,所以我添加了一个简单的检查,以便在达到 max_size
后删除旧条目。
You also never handled the max_size
situation, so I added a simple check to remove the older entry once the max_size
has been reached.
只有将项目添加到列表中时才会清除该字段;从你的问题中不清楚这是否是所希望的行为。
The field is only cleared if an item is added to the list; it is unclear from your question if that is the desired behavior.
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();
}
}
});
}
}
这篇关于具有历史功能的JavaFX可编辑ComboBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!