Java中的JComboBox筛选器 - 与外观无关

14

我有一个简单的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");以更改外观时,过滤器不起作用了。在Windows外观下,组合框只能输入一个字符,替换之前输入的字符。

输入“moun”后的不同输出

请告诉我发生了什么?Manoj Shrestha的回答在某种程度上有所帮助,但您能否提供其他建议来实现Java中的组合框过滤器?


1
为了更快地获得帮助,请发布一个SSCCE - Andrew Thompson
SSCCE是一个单一的代码示例,而不是两个。如文章中所述,将类降级为默认并将它们转储到与“main()”相同的源文件中。同时包括导入。至于不同的PLAFs,您可以在运行时提示要测试哪个。 - Andrew Thompson
1
好问题,我曾在使用本地PLAf(而不是metal)时偶尔看到Windows 7上的这种行为(更多时候是如此),可以确认您的结果。在Java 1.6.0_29-b11 中,我们可以排除它是“Java 7的错误”,但是我没有有关原因或解决方法的新信息或见解。:( - Andrew Thompson
@Andrew Thompson,请问他的陛下是否可以在Win7 / Java 7中测试我回答中的代码? - mKorbel
1
我这里没有Windows,所以我甚至无法测试,但请看看是否删除this.setSelectedItem(enteredText);可以解决您的问题(即使这不是您想要的)。如果可以,过滤器似乎与问题根本无关。 - kritzikratzi
显示剩余6条评论
5个回答

16

首先,您每次都在创建新模型,然后从代码中调用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);
    }
}

希望这对你有用。


感谢您的评论。但是它仍然无法正常工作。http://pastebin.com/CbDZ7Uhg - gtiwari333
如果您在开始输入之前先单击下拉菜单,则可以正常工作。这是我测试的方式。我正在编辑代码,使其无需单击下拉菜单即可正常工作。 - Ashwinee K Jha
请尝试编辑后的代码,应该能够正常运行 #2。关于 #1,最好保持弹出窗口的大小固定,以避免不必要的调整大小 / 闪烁。 - Ashwinee K Jha
我刚发现另一个问题- 3) 当我按ENTER键时,过滤列表中的第一项从未被选中。它只能通过鼠标单击来选择。另外,FYI,问题#2仍然存在。#1不是什么大问题。 - gtiwari333
在某些情况下,当JComboBox位于DefaultCellEditor中并在JTable中使用时,此方法无法正常工作。model.removeAllElements()会触发编辑停止事件,并且表格单元格内容会过早更新。 - Jason
显示剩余2条评论

9

非常详尽的回答,我认为这是一个很好的例子,说明了不同的外观和感觉在API中如何实现方法并工作。

  • KeyListener不是Swing JComponents的适当监听器,你需要使用KeyBindings来解决问题,

  • KeyListener是简单的异步操作,

  • JComboBox是复合JComponent,因此需要覆盖内部JComponents,所有来自KeyListener的输出都必须包装在invokeLater()中,注意我可以从复合JComponent创建事件,两次invokeLater()不会返回预期的GUI输出,只有Swing Timer和Swing Action才能正确地完成这项任务,所以为什么要麻烦自己去处理错误的方式呢?

代码

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&F

enter image description here

WindowsLookAndFeel L&F

enter image description here

Nimbus L&F

enter image description here

Metal L&F

enter image description here

来自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 64位/Java7的输出

Metal L&F

输入图像描述

Windows L&F (在JComboBox中的按钮附近有奇怪的空白)

输入图像描述

Nimbus L&F

输入图像描述

请随意编辑


谢谢,这真的是一个很长的答案。但我想要的是在我的JComboBox中添加过滤器,而不是自动完成功能。 - gtiwari333
@gt_ebuddy 抱歉,这是关于过滤的问题。为了从JTextComponent获得正确的输出,您必须仅使用Document / DocumentListener。 - mKorbel
我对使用DocumentListener进行了一些更改 - http://pastebin.com/btMHW9QR。但是出现错误:java.lang.IllegalStateException: Attempt to mutate in notification。看起来我们不能从其DocumentListener中修改JTextComponent的内容。您能否请看一下并评论该怎么办? - gtiwari333
2
@gt_ebuddy,请问为什么要重新发明轮子呢?不要这样做,否则你就必须替换文档。我在这里发送了由伟大思想家编写的优秀代码,请使用它或根据您的要求进行修改。 - mKorbel

2

嗨,我必须承认,自动完成并不过滤。但两个组件的意图应该是相同的 -> 更快的用户输入。自动完成在这方面表现得非常好;-) - Dudelilama
但是过滤器允许部分匹配,并允许从过滤(减少)列表中选择所需项目。 - gtiwari333
你可以尝试对项目进行排序,这样你就能获得类似的行为,而不会出现性能问题和其他不必要的问题。 - Dudelilama

2
显然,故障出现在使用的文本字段组件中。当使用Windows外观时,该组件中的文本会被选择,就像使用“textfield.selectAll();”一样,因此当您输入其他内容时,所选文本将从文本字段组件中清除。因此,在下面的代码中调整了该组件的插入符位置。它是如何工作的:首先将文本字段中当前插入符位置存储在变量“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**********/

将您的插入符代码与@Ashwinee的comboFilter()结合使用,可以创建最佳的可编辑ComboBox。谢谢! - Noor ul Ain

0

看起来,正如您所提到的那样,当用户在组合框中输入任何文本时,Windows外观会选择(突出显示)输入的文本。因此,当您按下另一个键时,它将替换之前的文本。因此,解决方案是不突出显示输入的文本。您可以通过在keylistener中添加以下语句之一来实现此目的。

textfield.setCaretPosition(textfield.getText().length());

或者

textfield.setSelectionStart(textfield.getText().length());

所以,你的键盘监听器应该是这样的:

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

2
永远不要这样做。例如,这将完全禁用光标键。当用户在文本中间单击并输入几个字符时,它也会产生绝对疯狂的结果。 - kritzikratzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接