我有一个简单的JComboBox过滤器代码:
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class FilterComboBox extends JComboBox {
private List<String> array;
public FilterComboBox(List<String> array) {
super(array.toArray());
this.array = array;
this.setEditable(true);
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
comboFilter(textfield.getText());
}
});
}
});
}
public void comboFilter(String enteredText) {
List<String> filterArray= new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {
if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(array.get(i));
}
}
if (filterArray.size() > 0) {
this.setModel(new DefaultComboBoxModel(filterArray.toArray()));
this.setSelectedItem(enteredText);
this.showPopup();
}
else {
this.hidePopup();
}
}
/* Testing Codes */
public static List<String> populateArray() {
List<String> test = new ArrayList<String>();
test.add("");
test.add("Mountain Flight");
test.add("Mount Climbing");
test.add("Trekking");
test.add("Rafting");
test.add("Jungle Safari");
test.add("Bungie Jumping");
test.add("Para Gliding");
return test;
}
public static void makeUI() {
JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
FilterComboBox acb = new FilterComboBox(populateArray());
frame.getContentPane().add(acb);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
makeUI();
}
}
组合过滤器的性能不是很好,但对于少数数据集来说它很好。我的问题是 - 当我删除评论UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
以更改外观时,过滤器不起作用。在WindowsLookAndFeel中,组合框仅通过替换先前输入的字符来获取单个字符。
你可以告诉我发生了什么事吗? Manoj Shrestha's answer below在某种程度上有所帮助,但是,您能否提供一些其他建议来实现Java中的组合框过滤器?
答案 0 :(得分:12)
首先,您每次都在创建新模型,然后从代码调用show popup导致闪烁等。我们可以修改模型本身。其次,您将当前输入的文本设置为所选项目,似乎具有其他人所指出的selectAll行为。我修改了代码如下:
public void comboFilter(String enteredText) {
if (!this.isPopupVisible()) {
this.showPopup();
}
List<String> filterArray= new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {
if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(array.get(i));
}
}
if (filterArray.size() > 0) {
DefaultComboBoxModel model = (DefaultComboBoxModel) this.getModel();
model.removeAllElements();
for (String s: filterArray)
model.addElement(s);
JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.setText(enteredText);
}
}
希望它适合你。
答案 1 :(得分:8)
很长的答案,我认为关于不同的外观和感觉如何在API中实现方法并且有效的例子
KeyListener不是Swing JComponents的正确监听器,你真的很想搞定KeyBindings,
KeyListener是简单的异步,
JComboBox是复合JComponent,然后需要覆盖内部JComponents,KeyListener的所有输出都必须包装到invokeLater()中,注意我可以从coumpond JComponents创建两次invokeLater()不返回预期输出的事件对于GUI,只有带Swing Action的Swing Timer可以正确地做到这一点,为什么要打扰这个关于错误方式的例子,这很简单,
码
import java.awt.Component;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class ComboBoxHoverOver {
private JComboBox combo = new JComboBox();
public ComboBoxHoverOver() {
combo.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXX");
combo.setRenderer(new ComboToolTipRenderer(combo));
combo.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
//System.out.println(combo.getSelectedItem().toString());
}
});
combo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//System.out.println(combo.getSelectedItem().toString());
}
});
combo.addItem("");
combo.addItem("Long text 4");
combo.addItem("Long text 3");
combo.addItem("Long text 2");
combo.addItem("Long text 1");
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(combo);
f.pack();
f.setVisible(true);
}
private class ComboToolTipRenderer extends BasicComboBoxRenderer {
private static final long serialVersionUID = 1L;
private JComboBox combo;
private JList comboList;
ComboToolTipRenderer(JComboBox combo) {
this.combo = combo;
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
if (comboList == null) {
comboList = list;
KeyAdapter listener = new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP) {
int x = 5;
int y = comboList.indexToLocation(comboList.getSelectedIndex()).y;
System.out.println(comboList.getSelectedIndex());
}
}
};
combo.addKeyListener(listener);
combo.getEditor().getEditorComponent().addKeyListener(listener);
}
if (isSelected) {
//System.out.println(value.toString());
}
return this;
}
}
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ComboBoxHoverOver comboBoxHoverOver = new ComboBoxHoverOver();
}
});
}
}
JComboBox是复合JComponent,然后需要覆盖BasicComboBoxUI,请抱歉我懒得编写和模拟代码太长的代码作为第一点的代码
否则所有来自上述两点的努力都是无用的和反作用的,没有别的,只有DOT
请有人来测试* nix和apple OS X中的代码
来自我的Java6 WinXP组件(所有重要的内容都隐藏在使用过的方法中,对前Sun Microsystems的匿名作者来说是无比的荣誉)
物质L&amp; F
WindowsLookAndFeel L&amp; F
Nimbus L&amp; F
金属L&amp; F
来自Java Classes
主
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import org.pushingpixels.substance.api.skin.SubstanceOfficeSilver2007LookAndFeel;
public class AutoCompleteTextField {
private static JFrame frame = new JFrame();
private ArrayList<String> listSomeString = new ArrayList<String>();
private Java2sAutoTextField someTextField = new Java2sAutoTextField(listSomeString);
private ArrayList<String> listSomeAnotherString = new ArrayList<String>();
private Java2sAutoComboBox someComboBox = new Java2sAutoComboBox(listSomeAnotherString);
public AutoCompleteTextField() {
listSomeString.add("-");
listSomeString.add("Snowboarding");
listSomeString.add("Rowing");
listSomeString.add("Knitting");
listSomeString.add("Speed reading");
listSomeString.add("Pool");
listSomeString.add("None of the above");
//
listSomeAnotherString.add("-");
listSomeAnotherString.add("XxxZxx Snowboarding");
listSomeAnotherString.add("AaaBbb Rowing");
listSomeAnotherString.add("CccDdd Knitting");
listSomeAnotherString.add("Eee Fff Speed reading");
listSomeAnotherString.add("Eee Fff Pool");
listSomeAnotherString.add("Eee Fff None of the above");
//
someTextField.setFont(new Font("Serif", Font.BOLD, 16));
someTextField.setForeground(Color.black);
someTextField.setBackground(Color.orange);
someTextField.setName("someTextField");
someTextField.setDataList(listSomeString);
//
someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
someComboBox.setForeground(Color.black);
someComboBox.setBackground(Color.YELLOW);
someComboBox.getEditor().selectAll();
someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
((JTextField) someComboBox.getEditor().getEditorComponent()).setDisabledTextColor(Color.black);
someComboBox.setName("someComboBox");
someComboBox.setDataList(listSomeAnotherString);
//
frame.setLayout(new GridLayout(0, 1, 10, 10));
frame.add(someTextField);
frame.add(someComboBox);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
//
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
someTextField.setText("-");
someComboBox.getEditor().setItem(0);
someComboBox.getEditor().selectAll();
someTextField.grabFocus();
someTextField.requestFocus();
someTextField.setText(someTextField.getText());
someTextField.selectAll();
}
});
}
public static void main(String[] args) {
/*SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(new SubstanceOfficeSilver2007LookAndFeel());
SwingUtilities.updateComponentTreeUI(frame);
} catch (UnsupportedLookAndFeelException e) {
throw new RuntimeException(e);
}
}
});*/
/*try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
System.out.println(info.getName());
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (UnsupportedLookAndFeelException e) {
// handle exception
} catch (ClassNotFoundException e) {
// handle exception
} catch (InstantiationException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}*/
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
AutoCompleteTextField aCTF = new AutoCompleteTextField();
}
});
}
}
AutoComboBox
import java.awt.event.ItemEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.plaf.basic.BasicComboBoxEditor;
public class Java2sAutoComboBox extends JComboBox {
private static final long serialVersionUID = 1L;
private AutoTextFieldEditor autoTextFieldEditor;
private boolean isFired;
private class AutoTextFieldEditor extends BasicComboBoxEditor {
private Java2sAutoTextField getAutoTextFieldEditor() {
return (Java2sAutoTextField) editor;
}
AutoTextFieldEditor(java.util.List<String> list) {
editor = new Java2sAutoTextField(list, Java2sAutoComboBox.this);
}
}
public Java2sAutoComboBox(java.util.List<String> list) {
isFired = false;
autoTextFieldEditor = new AutoTextFieldEditor(list);
setEditable(true);
setModel(new DefaultComboBoxModel(list.toArray()) {
private static final long serialVersionUID = 1L;
@Override
protected void fireContentsChanged(Object obj, int i, int j) {
if (!isFired) {
super.fireContentsChanged(obj, i, j);
}
}
});
setEditor(autoTextFieldEditor);
}
public boolean isCaseSensitive() {
return autoTextFieldEditor.getAutoTextFieldEditor().isCaseSensitive();
}
public void setCaseSensitive(boolean flag) {
autoTextFieldEditor.getAutoTextFieldEditor().setCaseSensitive(flag);
}
public boolean isStrict() {
return autoTextFieldEditor.getAutoTextFieldEditor().isStrict();
}
public void setStrict(boolean flag) {
autoTextFieldEditor.getAutoTextFieldEditor().setStrict(flag);
}
public java.util.List<String> getDataList() {
return autoTextFieldEditor.getAutoTextFieldEditor().getDataList();
}
public void setDataList(java.util.List<String> list) {
autoTextFieldEditor.getAutoTextFieldEditor().setDataList(list);
setModel(new DefaultComboBoxModel(list.toArray()));
}
void setSelectedValue(Object obj) {
if (isFired) {
return;
} else {
isFired = true;
setSelectedItem(obj);
fireItemStateChanged(new ItemEvent(this, 701, selectedItemReminder, 1));
isFired = false;
return;
}
}
@Override
protected void fireActionEvent() {
if (!isFired) {
super.fireActionEvent();
}
}
}
AutoTextField
import java.util.List;
import javax.swing.JTextField;
import javax.swing.text.*;
public class Java2sAutoTextField extends JTextField {
private static final long serialVersionUID = 1L;
private List<String> dataList;
private boolean isCaseSensitive;
private boolean isStrict;
private Java2sAutoComboBox autoComboBox;
public class AutoDocument extends PlainDocument {
private static final long serialVersionUID = 1L;
@Override
public void replace(int i, int j, String s, AttributeSet attributeset)
throws BadLocationException {
super.remove(i, j);
insertString(i, s, attributeset);
}
@Override
public void insertString(int i, String s, AttributeSet attributeset)
throws BadLocationException {
if (s == null || "".equals(s)) {
return;
}
String s1 = getText(0, i);
String s2 = getMatch(s1 + s);
int j = (i + s.length()) - 1;
if (isStrict && s2 == null) {
s2 = getMatch(s1);
j--;
} else if (!isStrict && s2 == null) {
super.insertString(i, s, attributeset);
return;
}
if (autoComboBox != null && s2 != null) {
autoComboBox.setSelectedValue(s2);
}
super.remove(0, getLength());
super.insertString(0, s2, attributeset);
setSelectionStart(j + 1);
setSelectionEnd(getLength());
}
@Override
public void remove(int i, int j) throws BadLocationException {
int k = getSelectionStart();
if (k > 0) {
k--;
}
String s = getMatch(getText(0, k));
if (!isStrict && s == null) {
super.remove(i, j);
} else {
super.remove(0, getLength());
super.insertString(0, s, null);
}
if (autoComboBox != null && s != null) {
autoComboBox.setSelectedValue(s);
}
try {
setSelectionStart(k);
setSelectionEnd(getLength());
} catch (Exception exception) {
}
}
}
public Java2sAutoTextField(List<String> list) {
isCaseSensitive = false;
isStrict = true;
autoComboBox = null;
if (list == null) {
throw new IllegalArgumentException("values can not be null");
} else {
dataList = list;
init();
return;
}
}
Java2sAutoTextField(List<String> list, Java2sAutoComboBox b) {
isCaseSensitive = false;
isStrict = true;
autoComboBox = null;
if (list == null) {
throw new IllegalArgumentException("values can not be null");
} else {
dataList = list;
autoComboBox = b;
init();
return;
}
}
private void init() {
setDocument(new AutoDocument());
if (isStrict && dataList.size() > 0) {
setText(dataList.get(0).toString());
}
}
private String getMatch(String s) {
for (int i = 0; i < dataList.size(); i++) {
String s1 = dataList.get(i).toString();
if (s1 != null) {
if (!isCaseSensitive
&& s1.toLowerCase().startsWith(s.toLowerCase())) {
return s1;
}
if (isCaseSensitive && s1.startsWith(s)) {
return s1;
}
}
}
return null;
}
@Override
public void replaceSelection(String s) {
AutoDocument _lb = (AutoDocument) getDocument();
if (_lb != null) {
try {
int i = Math.min(getCaret().getDot(), getCaret().getMark());
int j = Math.max(getCaret().getDot(), getCaret().getMark());
_lb.replace(i, j - i, s, null);
} catch (Exception exception) {
}
}
}
public boolean isCaseSensitive() {
return isCaseSensitive;
}
public void setCaseSensitive(boolean flag) {
isCaseSensitive = flag;
}
public boolean isStrict() {
return isStrict;
}
public void setStrict(boolean flag) {
isStrict = flag;
}
public List<String> getDataList() {
return dataList;
}
public void setDataList(List<String> list) {
if (list == null) {
throw new IllegalArgumentException("values can not be null");
} else {
dataList = list;
return;
}
}
}
修改
Win7 64b / Java7的输出
金属L&amp; F
Windows L&amp; F(JComboBox中Button附近有趣的空白空间)
Nimbus L&amp; F
随意编辑
答案 2 :(得分:1)
此组件称为自动完成,并包含在所谓的swing扩展项中。
请看一下:http://swingx.java.net/
有一个webstart:http://swinglabs-demos.java.net/demos/swingxset6/swingxset.jnlp
自动填充是要选择的菜单。享受乐趣,减少错误代码:)
答案 3 :(得分:1)
显然,故障是在使用的文本域组件中。所发生的情况是,当使用Windows外观时,使用“textfield.selectAll();”行选择此组件中的文本,因此当您键入任何其他内容时,将从textfield组件中清除所选文本。因此,在下面的代码中,调整了该组件的插入位置。这是它的工作原理,首先将文本字段的当前插入位置存储在变量“currentCaretPosition”中,然后将插入位置移动到组件中文本的开头。过滤后将插入位置恢复为“currentCaretPosition”变量值。我希望它能按你的意愿运作。
精炼代码如下: -
/****Beginning of code****/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class FilterComboBox extends JComboBox {
private List<String> array;
private int currentCaretPosition=0;
public FilterComboBox(List<String> array) {
super(array.toArray());
this.array = array;
this.setEditable(true);
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
currentCaretPosition=textfield.getCaretPosition();
if(textfield.getSelectedText()==null)
{
textfield.setCaretPosition(0);
comboFilter(textfield.getText());
textfield.setCaretPosition(currentCaretPosition);
}
}
});
}
});
}
public void comboFilter(String enteredText) {
List<String> filterArray= new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {
if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(array.get(i));
}
}
if (filterArray.size() > 0) {
this.setModel(new DefaultComboBoxModel(filterArray.toArray()));
this.setSelectedItem(enteredText);
this.showPopup();
}
else {
this.hidePopup();
}
}
/* Testing Codes */
public static List<String> populateArray() {
List<String> test = new ArrayList<String>();
test.add("");
test.add("Mountain Flight");
test.add("Mount Climbing");
test.add("Trekking");
test.add("Rafting");
test.add("Jungle Safari");
test.add("Bungie Jumping");
test.add("Para Gliding");
return test;
}
public static void makeUI() {
JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
FilterComboBox acb = new FilterComboBox(populateArray());
frame.getContentPane().add(acb);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
makeUI();
}
}
/******* End of code**********/
答案 4 :(得分:0)
正如您所提到的,当用户在组合框中输入任何文本时,它看起来像是Windows外观和视频。感觉选择(突出显示)输入的文本。因此,当您按另一个键时,它将替换前一个键。因此,解决方案不是突出显示输入的文本。您可以通过在keylistener中添加以下任何一个语句来实现此目的。
textfield.setCaretPosition(textfield.getText().length());
OR
textfield.setSelectionStart(textfield.getText().length());
所以,你的keylistener应该是这样的:
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
comboFilter(textfield.getText());
textfield.setCaretPosition(textfield.getText().length());
}
});
}
});