提问者:小点点

Java 中的 jcombobox filter - 外观和感觉独立


我有一个简单的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下面的回答在某种程度上有所帮助,但是,您能否提供一些其他建议来实现Java中的组合框过滤器?


共3个答案

匿名用户

首先,您每次都创建新模型,然后从代码中调用显示弹出窗口,从而导致闪烁等。我们可以修改模型本身。其次,您将当前输入的文本设置为所选项目,该项目似乎具有其他人指出的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);
    }
}

希望它对你有用。

匿名用户

很长的答案,我认为关于不同外观和感觉如何在 API 中实现方法并正常工作的出色示例

>

  • KeyListener 不是适合 Swing JComponents 的监听器,你真的要打扰 KeyBindings,

    KeyListener 是简单的异步,

    JComboBox 是复合 JComponent,然后需要覆盖内部 JComponent,KeyListener 的所有输出都必须包装到 invokeLater() 中,请注意我可以从 coumpond JComponents 创建事件,两次调用 inbykeLater() 不会将预期的输出返回给 GUI,只有带有摆动动作的 Swing 计时器才能正确做到这一点,很简单为什么要打扰那个关于错误方式的例子,

    法典

    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 和苹果 OS X 中的代码进行测试

    来自我的Java6 WinXP组合(所有重要的东西都隐藏在使用的方法中,对前Sun Microsystems的匿名作者表示无尽的赞誉)

    物质 L

    WindowsLookAndFeel L

    雨云 L

    金属 L

    从 Java 类

    主要

    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();
                }
            });
        }
    }
    

    自动组合框

    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();
            }
        }
    }
    

    自动图文集字段

    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

    视窗 L

    雨云 L

    随意编辑

  • 匿名用户

    此组件称为自动完成,包含在所谓的摆动扩展 porject 中。

    看看: http://swingx.java.net/
    有一个网络启动: http://swinglabs-demos.java.net/demos/swingxset6/swingxset.jnlp

    自动完成是要选择的菜单。玩得开心,代码:)不易出错