我有一个JTextField,希望为其提供与用户输入相匹配的结果。我在一个包含在一个JList中的JPopupMenu中显示这些建议。
但是,当通过show(Component invoker, int x, int y)以编程方式打开弹出菜单时,焦点将从JTextField中移除。
奇怪的是,如果我调用setVisible(true),焦点不会被窃取;但是JPopupMenu不会附加到任何面板上,并且当在打开框时最小化应用程序时,它会保持在窗口上。
我还尝试使用JTextField将焦点重置为requestFocus(),但随后我必须使用SwingUtilities.invokeLater()恢复插入符号位置,而调用的后面部分给用户提供了一点空间来处理现有的内容/覆盖它/或做其他不可预知的事情。
我得到的代码实际上是:
JTextField field = new JTextField();
JPopupMenu menu = new JPopupMenu();
field.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
JList list = getAListOfResults();
menu.add(list);
menu.show(field, 0, field.getHeight());
}
});有谁能建议在保持对JPopupMenu的关注的同时,以编程方式显示JTextField的最佳途径?
发布于 2012-04-06 11:38:20
技术上的答案是将弹出窗口的可聚焦属性设置为false:
popup.setFocusable(false);这意味着textField必须接管通常由列表本身处理的所有键盘和鼠标触发的操作,比如:
final JList list = new JList(Locale.getAvailableLocales());
final JPopupMenu popup = new JPopupMenu();
popup.add(new JScrollPane(list));
popup.setFocusable(false);
final JTextField field = new JTextField(20);
Action down = new AbstractAction("nextElement") {
@Override
public void actionPerformed(ActionEvent e) {
int next = Math.min(list.getSelectedIndex() + 1,
list.getModel().getSize() - 1);
list.setSelectedIndex(next);
list.ensureIndexIsVisible(next);
}
};
field.getActionMap().put("nextElement", down);
field.getInputMap().put(
KeyStroke.getKeyStroke("DOWN"), "nextElement");由于您的上下文非常类似于JComboBox,您可能会考虑查看BasicComboBoxUI和BasicComboPopup的来源。
编辑
只是为了好玩,下面没有回答焦点问题:-)相反,它演示了如何使用可排序/可过滤的JXList来只显示下拉列表中与类型化文本对应的选项(这里有一个开始- with规则)
// instantiate a sortable JXList
final JXList list = new JXList(Locale.getAvailableLocales(), true);
list.setSortOrder(SortOrder.ASCENDING);
final JPopupMenu popup = new JPopupMenu();
popup.add(new JScrollPane(list));
popup.setFocusable(false);
final JTextField field = new JTextField(20);
// instantiate a PatternModel to map text --> pattern
final PatternModel model = new PatternModel();
model.setMatchRule(PatternModel.MATCH_RULE_STARTSWITH);
// listener which to update the list's RowFilter on changes to the model's pattern property
PropertyChangeListener modelListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("pattern".equals(evt.getPropertyName())) {
updateFilter((Pattern) evt.getNewValue());
}
}
private void updateFilter(Pattern newValue) {
RowFilter<Object, Integer> filter = null;
if (newValue != null) {
filter = RowFilters.regexFilter(newValue);
}
list.setRowFilter(filter);
}
};
model.addPropertyChangeListener(modelListener);
// DocumentListener to update the model's rawtext property on changes to the field
DocumentListener documentListener = new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
updateAfterDocumentChange();
}
@Override
public void insertUpdate(DocumentEvent e) {
updateAfterDocumentChange();
}
private void updateAfterDocumentChange() {
if (!popup.isVisible()) {
popup.show(field, 0, field.getHeight());
}
model.setRawText(field.getText());
}
@Override
public void changedUpdate(DocumentEvent e) {
}
};
field.getDocument().addDocumentListener(documentListener);发布于 2012-04-05 17:34:31
它对我来说是向前看的。添加以下内容
field.requestFocus();
之后
menu.add(list);
menu.show(field, 0, field.getHeight());当然,您必须根据JTextField正在发生的情况,为何时隐藏弹出窗口等编写代码。
即;
menu.show(field, field.getX(), field.getY()+field.getHeight());
menu.setVisible(true);
field.requestFocus();发布于 2012-08-10 12:39:07
您可以看看JXSearchField,它是新灵的一部分
https://stackoverflow.com/questions/10029846
复制相似问题