Java Swing中可搜索的下拉框存在问题
我已经做了一个可搜索的组合框,供Java Swing程序使用。
下面是我希望它的工作方式:
- 点击后,它会展开选项列表,并允许在文本框中输入,以便用户通过多词搜索来查找选项。
- 在搜索过程中找到选项时,用户可以单击任意一个选项,使组合框的值设为该项。如果没有找到选项,列表将为空。
- 当用户单击组合框之外的位置时,文本框中的输入将被禁用,选项列表也会隐藏。如果在搜索过程中没有进行任何选择,组合框将恢复为最近一次的选择,若没有选择则恢复为默认项。
以下是问题:当用户输入搜索且有可用选项时,并且他们单击组合框之外,组合框(以及其中的文本)将设置为默认值(或最近选择的项)。这正是我想要的。但当搜索中没有找到选项时,单击组合框之外,内部文本不会改变。
以下是代码:
CustomClass[] items = customClassList.toArray(new CustomClass[customClassList.size()]);
comboBox = new JComboBox<CustomClass>(items);
selectedMenuItem = comboBox.getItemAt(0);
currentCustomClassID = selectedMenuItem.getCustomClassID();
Dimension comboBoxSize = comboBox.getPreferredSize();
comboBoxSize.height = 25;
comboBoxSize.width = 500;
comboBox.setMinimumSize(comboBoxSize);
comboBox.setMaximumSize(comboBoxSize);
comboBox.setPreferredSize(comboBoxSize);
comboBox.addActionListener(e -> {
Object selected = comboBox.getSelectedItem();
if (selected instanceof CustomClass) {
selectedMenuItem = (CustomClass) selected;
comboBox.setEditable(false);
currentCustomClassID = selectedMenuItem.getCustomClassID();
}
});
JTextField editor = (JTextField) comboBox.getEditor().getEditorComponent();
menuPane.add(comboBox);
comboBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
comboBox.setEditable(true);
});
comboBox.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
// Popup is opening
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
// This is where the text inside the box should change when the user clicks outside the combo box. It changes when there are options available, but not if the options list is empty
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
comboBox.setEditable(false);
editor.setText(selectedMenuItem.toString());
comboBox.setSelectedItem(selectedMenuItem);
}
});
editor.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
comboBox.setEditable(true);
editor.setText("");
comboBox.showPopup();
}
});
editor.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
String text = editor.getText();
String[] keywords = text.toLowerCase().split(" ");
// Filter items that contain all keywords
Vector<CustomClass> filteredItems = new Vector<>();
for (CustomClass item : items) {
boolean match = true;
for (String keyword : keywords) {
if (!item.toString().toLowerCase().contains(keyword)) {
match = false;
break;
}
}
if (match) filteredItems.add(item);
}
// Update Model
DefaultComboBoxModel<CustomClass> newModel = new DefaultComboBoxModel<>(filteredItems);
comboBox.setModel(newModel);
comboBox.setSelectedItem(text);
comboBox.showPopup();
}
});
为什么在有选项可用时,editor.setText(selectedMenuItem.toString()); 这一行才起作用,而在搜索时没有找到选项时却不起作用?
解决方案
你的
editor.setText(selectedMenuItem.toString());
这一行假设 selectedMenuItem 非空。然而,它也可能是 null,尤其是在你没有要选择的项时。在这种情况下,你需要像下面这样为文本设定默认值:
editor.setText((selectedMenuItem != null) ? selectedMenuItem.toString() : "");
产生你所经历的行为的原因在于,当你执行以下操作时
selectedMenuItem = comboBox.getItemAt(0);
当没有元素时,0越界,在这种情况下,getItemAt 将返回 null。你还需要
comboBox.addActionListener(e -> {
Object selected = comboBox.getSelectedItem();
if (selected instanceof CustomClass) {
selectedMenuItem = (CustomClass) selected;
comboBox.setEditable(false);
currentCustomClassID = selectedMenuItem.getCustomClassID();
}
});
在选择一个 CustomClass 实例时初始化 selectedMenuItem。现在,如果这段代码真的在运行,那么它不会进入 if 的内部块,因为 null 不是一个 instanceof CustomClass。
因此在空的组合框的情况下,selectedMenuItem 将最终变为 null,你需要在使用处对这种情景添加保护。你也许想实现辅助方法以避免重复代码。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。