我正在寻找一种将自动完成添加到 JavaFX ComboBox
的方法。
这 AutoFillBox
是已知的,但不是我正在搜索的。我想要的是一个可编辑的 ComboBox,并且在键入列表时应该进行过滤。但我也想在不输入和查看整个项目的情况下打开列表。
任何想法?
原文由 JulianG 发布,翻译遵循 CC BY-SA 4.0 许可协议
我正在寻找一种将自动完成添加到 JavaFX ComboBox
的方法。
这 AutoFillBox
是已知的,但不是我正在搜索的。我想要的是一个可编辑的 ComboBox,并且在键入列表时应该进行过滤。但我也想在不输入和查看整个项目的情况下打开列表。
任何想法?
原文由 JulianG 发布,翻译遵循 CC BY-SA 4.0 许可协议
首先,您必须在您的项目中创建此类:
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.ComboBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public class FxUtilTest {
public interface AutoCompleteComparator<T> {
boolean matches(String typedText, T objectToCompare);
}
public static<T> void autoCompleteComboBoxPlus(ComboBox<T> comboBox, AutoCompleteComparator<T> comparatorMethod) {
ObservableList<T> data = comboBox.getItems();
comboBox.setEditable(true);
comboBox.getEditor().focusedProperty().addListener(observable -> {
if (comboBox.getSelectionModel().getSelectedIndex() < 0) {
comboBox.getEditor().setText(null);
}
});
comboBox.addEventHandler(KeyEvent.KEY_PRESSED, t -> comboBox.hide());
comboBox.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
private boolean moveCaretToPos = false;
private int caretPos;
@Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.UP) {
caretPos = -1;
if (comboBox.getEditor().getText() != null) {
moveCaret(comboBox.getEditor().getText().length());
}
return;
} else if (event.getCode() == KeyCode.DOWN) {
if (!comboBox.isShowing()) {
comboBox.show();
}
caretPos = -1;
if (comboBox.getEditor().getText() != null) {
moveCaret(comboBox.getEditor().getText().length());
}
return;
} else if (event.getCode() == KeyCode.BACK_SPACE) {
if (comboBox.getEditor().getText() != null) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
} else if (event.getCode() == KeyCode.DELETE) {
if (comboBox.getEditor().getText() != null) {
moveCaretToPos = true;
caretPos = comboBox.getEditor().getCaretPosition();
}
} else if (event.getCode() == KeyCode.ENTER) {
return;
}
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT || event.getCode().equals(KeyCode.SHIFT) || event.getCode().equals(KeyCode.CONTROL)
|| event.isControlDown() || event.getCode() == KeyCode.HOME
|| event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) {
return;
}
ObservableList<T> list = FXCollections.observableArrayList();
for (T aData : data) {
if (aData != null && comboBox.getEditor().getText() != null && comparatorMethod.matches(comboBox.getEditor().getText(), aData)) {
list.add(aData);
}
}
String t = "";
if (comboBox.getEditor().getText() != null) {
t = comboBox.getEditor().getText();
}
comboBox.setItems(list);
comboBox.getEditor().setText(t);
if (!moveCaretToPos) {
caretPos = -1;
}
moveCaret(t.length());
if (!list.isEmpty()) {
comboBox.show();
}
}
private void moveCaret(int textLength) {
if (caretPos == -1) {
comboBox.getEditor().positionCaret(textLength);
} else {
comboBox.getEditor().positionCaret(caretPos);
}
moveCaretToPos = false;
}
});
}
public static<T> T getComboBoxValue(ComboBox<T> comboBox){
if (comboBox.getSelectionModel().getSelectedIndex() < 0) {
return null;
} else {
return comboBox.getItems().get(comboBox.getSelectionModel().getSelectedIndex());
}
}
}
要使您的 ComboBox
自动完成,请像这样使用它:
FxUtilTest.autoCompleteComboBoxPlus(myComboBox, (typedText, itemToCompare) -> itemToCompare.getName().toLowerCase().contains(typedText.toLowerCase()) || itemToCompare.getAge().toString().equals(typedText));
然后,添加一个 StringConverter
如下例(因为 ComboBox
值将返回一个 String
并且必须将其转换为您的对象):
myComboBox.setConverter(new StringConverter<>() {
@Override
public String toString(YourObject object) {
return object != null ? object.getName() : "";
}
@Override
public YourObject fromString(String string) {
return myComboBox.getItems().stream().filter(object ->
object.getName().equals(string)).findFirst().orElse(null);
}
});
当您需要从组合框中获取选定的值时,也请务必使用此方法,否则您可能会遇到一些异常,如“类强制转换异常”:
FxUtilTest.getComboBoxValue(myComboBox);
PS:此方法在 JRE 8.51 和 8.65 之间的版本中存在一些问题,导致一些奇怪的行为,现在这些问题似乎不再发生。如果您遇到一些问题,您可以看到对此答案所做的编辑并获得当时解决问题的旧版本。此方法必须正常工作,如果您遇到任何问题,请告诉我。
原文由 Mateus Viccari 发布,翻译遵循 CC BY-SA 4.0 许可协议
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答6k 阅读
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
我找到了适合我的解决方案:
你可以用
它基于 此,我对其进行了定制以满足我的需要。
随意使用它,如果有人可以改进它,请告诉我。