【问题标题】:JComboBox search listJComboBox 搜索列表
【发布时间】:2015-03-01 10:43:40
【问题描述】:

我想创建一个JComboBox,内容可以搜索。 我试过AutoCompleteDecorator, GlazedLists, SwingLabs, JIDE, Laf-Widget,但所有的都不能用第二个关键字搜索。 例如,在此代码中,可能按第一个字母进行搜索,而此内容仅包含一个单词。

this.comboBox = new JComboBox(new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });
AutoCompleteDecorator.decorate(this.comboBox);

如果JComboBox内容由2或3个单词组成,例如:“Ester Jordi”或“Jorge Sergi”,在这种情况下如果我输入“Sergi”,JComboBox不显示任何内容,因为它可以识别按第一个字。 请问有什么办法可以解决这个问题吗?

【问题讨论】:

  • 我找到了这个 FilterComboBox: stackoverflow.com/questions/10368856/… 。我的 JFrame 包含许多带有长行数据的组合框,为了快速搜索,我需要一个 SuggestField 作为 Google。问题是我不知道如何将此代码应用于我的 JFrame。
  • @Marius Žilėnas:很抱歉耽搁了这么久。我遵循了您的建议,但仍然无法成功使用 ComboBox 搜索部分。我仍然不清楚 rewrite that part to search in that index 。如果可能的话,您能否提供一些代码。非常感谢您的帮助。
  • @Marius Žilėnas: 1) 词索引:String[] data = new String[] {"English", "French", "Spanish", "Japanese", "Chinese"}; for(int i=0; i < data.length; i++){ jComboBox1.addItem(data[i]); jComboBox1.setEditable(true); 2) {if data.get(i).toLowerCase().contains(enteredText.toLowerCase())) {filterArray.add(data.get(i)); 我不知道我认为我走错了路。我完全迷失在搜索部分。

标签: java swing autocomplete jcombobox netbeans-8


【解决方案1】:

我重构了给定的代码。它可以通过片段识别。所以“美式英语”和“英语”在输入“English”时都会被识别出来。

您可以在程序中使用 FilterComboBox 类。

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.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * A class for filtered combo box.
 */
public class FilterComboBox
    extends JComboBox
{
    /**
     * Entries to the combobox list.
     */
    private List<String> entries;

    public List<String> getEntries()
    {
        return entries;
    }

    public FilterComboBox(List<String> entries)
    {
        super(entries.toArray());
        this.entries = entries  ;
        this.setEditable(true);

        final JTextField textfield =
            (JTextField) this.getEditor().getEditorComponent();

        /**
         * Listen for key presses.
         */
        textfield.addKeyListener(new KeyAdapter()
        {
            public void keyReleased(KeyEvent ke)
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        /**
                         * On key press filter the list.
                         * If there is "text" entered in text field of this combo use that "text" for filtering.
                         */
                        comboFilter(textfield.getText());
                    }
                });
            }
        });

    }

    /**
     * Build a list of entries that match the given filter.
     */
    public void comboFilter(String enteredText)
    {
        List<String> entriesFiltered = new ArrayList<String>();

        for (String entry : getEntries())
        {
            if (entry.toLowerCase().contains(enteredText.toLowerCase()))
            {
                entriesFiltered.add(entry);
            }
        }

        if (entriesFiltered.size() > 0)
        {
            this.setModel(
                    new DefaultComboBoxModel(
                        entriesFiltered.toArray()));
            this.setSelectedItem(enteredText);
            this.showPopup();
        }
        else
        {
            this.hidePopup();
        }
    }
}

在演示程序中查看 FilterComboBox 的工作原理。

import javax.swing.JFrame;
import java.util.Arrays;

public class Demo
{
    public static void makeUI()
    {
        JFrame frame = new JFrame("Your frame");
        /**
         * Put data to your filtered combobox.
         */
        FilterComboBox fcb = new FilterComboBox(
                Arrays.asList(
                    "",
                    "English", 
                    "French", 
                    "Spanish", 
                    "Japanese",
                    "Chinese",
                    "American English",
                    "Canada French"
                    ));
        /**
         * Set up the frame.
         */
        frame.getContentPane().add(fcb);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception
    {
        makeUI();
    }
}

另一种方法,我们将现有的组合框变成过滤的组合框。这有点“装饰”。

“装饰器”类。

import java.util.List;
import java.util.ArrayList;

import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.DefaultComboBoxModel;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * Makes given combobox editable and filterable.
 */ 
public class JComboBoxDecorator
{
    public static void decorate(final JComboBox jcb, boolean editable)
    {
        List<String> entries = new ArrayList<>();
        for (int i = 0; i < jcb.getItemCount(); i++)
        {
            entries.add((String)jcb.getItemAt(i));
        }

        decorate(jcb, editable, entries);
    }

    public static void decorate(final JComboBox jcb, boolean editable, final List<String> entries)
    {
        jcb.setEditable(editable);
        jcb.setModel(
                    new DefaultComboBoxModel(
                        entries.toArray()));

        final JTextField textField = (JTextField) jcb.getEditor().getEditorComponent();

        textField.addKeyListener(
            new KeyAdapter()
            {
                public void keyReleased(KeyEvent e)
                {
                    SwingUtilities.invokeLater(
                        new Runnable()
                        {
                            public void run()
                            { 
                                comboFilter(textField.getText(), jcb, entries);
                            }
                        }
                    );
                } 
            }
        );
    }

    /**
     * Build a list of entries that match the given filter.
     */
    private static void comboFilter(String enteredText, JComboBox jcb, List<String> entries)
    {
        List<String> entriesFiltered = new ArrayList<String>();

        for (String entry : entries)
        {
            if (entry.toLowerCase().contains(enteredText.toLowerCase()))
            {
                entriesFiltered.add(entry);
            }
        }

        if (entriesFiltered.size() > 0)
        {
            jcb.setModel(
                    new DefaultComboBoxModel(
                        entriesFiltered.toArray()));
            jcb.setSelectedItem(enteredText);
            jcb.showPopup();
        }
        else
        {
            jcb.hidePopup();
        }
    }

}

示范课。

import javax.swing.JFrame;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;

import javax.swing.JComboBox;
import javax.swing.JPanel;

public class Demo
{
    public static void makeUI()
    {
        JFrame frame = new JFrame("Demonstration");

        /**
         * List of values for comboboxes.
         */
        List<String> list = Arrays.asList( 
            "",
            "English", 
            "French", 
            "Spanish", 
            "Japanese",
            "Chinese",
            "American English",
            "Canada French"
        );

        List<String> list2 = Arrays.asList( 
            "",
            "Anglais", 
            "Francais", 
            "Espagnol", 
            "Japonais",
            "Chinois",
            "Anglais americain",
            "Canada francais"
        );

        /**
         * Set up the frame.
         */
        JPanel panel = new JPanel();
        frame.add(panel);

        /**
         * Create ordinary comboboxes.
         * These comboboxes represent premade combobox'es. Later in the run-time we make some of them filtered.
         */
        JComboBox<String> jcb1 = new JComboBox<>(list.toArray(new String[0]));
        panel.add(jcb1);

        JComboBox<String> jcb2 = new JComboBox<>();
        panel.add(jcb2);

        JComboBox<String> jcb3 = new JComboBox<>(list2.toArray(new String[0]));
        panel.add(jcb3);

        /**
         * On the run-time we convert second and third combobox'es to filtered combobox'es.
         * The jcb1 combobox is left as it was.
         * For the first decorated combobox supply our entries.
         * For the other put entries from list2.
         */
        JComboBoxDecorator.decorate(jcb2, true, list); 
        JComboBoxDecorator.decorate(jcb3, true); 

        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception
    {
        makeUI();
    }
}

【讨论】:

  • 我认为@Marius Žilėnas 的回答有助于解决以下链接中的问题:[stackoverflow.com/questions/10368856/…
  • 我想问一下,我可以为我的JComboBoxes 使用FilterComboBox 类作为jComboBox1.add(fcb); jComboBox2.add(fcb); 吗?
  • 使用JComboBoxDecorator.decorate(jComboBox2, true) 调用jComboBox2 被过滤。 :)
  • 非常感谢“装饰师”课程。我非常感谢您的时间和精力。对不起,如果我打扰了你。我可以将您的代码应用到我生成的JComboBoxes。但另一个问题是JComboBox 起初它显示空列表,然后当我输入文本时,那一刻出现了JComboBox 的项目。请问JComboBox的物品怎么更新?
  • 我接受了你的回答,并为你的善良和专业给你 +1。 (^~^)
【解决方案2】:

在尝试执行的时候,遇到了两个问题:

  • 当按下键盘上的(向上、向下、回车)按钮时。我通过使用return 语句阻止它们来解决它。

  • 每次您在文本字段中写入时都会触发 popupMenuWillBecomeInvisble()。 我通过添加getKeyStat()popupMenuWillBecomeInvisible内的主框架中添加此代码来解决它

希望这会有所帮助!

   private voidjCombobox1popupMenuWillBecomeInvisble(javax.swing.event.PopupMenuEvent evt){
         if(JComboBoxDecorator.getKeyStat().equals("enter")){
           //write yor code here
        }
        }

import java.util.List;
import java.util.ArrayList;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.DefaultComboBoxModel;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.SwingUtilities;

/**
 * Makes given combo box editable and filterable.
 */
public class JComboBoxDecorator {
    static String checkenter="";
    
    public static String getKeyStat(){
       return checkenter;
    }
    
    public static void decorate(final JComboBox jcb, boolean editable) {
        List<String> entries = new ArrayList<>();
        for (int i = 0; i < jcb.getItemCount(); i++) {
            entries.add((String) jcb.getItemAt(i));
        }

        decorate(jcb, editable, entries);
    }
    
    public static void decorate(final JComboBox jcb, boolean editable, final List<String> entries) {
        jcb.setEditable(editable);
        jcb.setModel(new DefaultComboBoxModel(entries.toArray()));

        final JTextField textField = (JTextField) jcb.getEditor().getEditorComponent();

        textField.addKeyListener(
                new KeyAdapter() {
                    @Override
                    public void keyPressed(KeyEvent e) {
                     if(e.getKeyCode() == KeyEvent.VK_ENTER){
                         checkenter = "enter";
                     }
                    }
            @Override
            public void keyReleased(KeyEvent e) {
                SwingUtilities.invokeLater(() -> {
                   if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode()==KeyEvent.VK_ENTER){
                      // e.consume();
                       return ;                       
                   }  
                   else{ 
                       comboFilter(textField.getText(), jcb, entries);
                   }
                    
                });
                checkenter = "type";
            }
        }
        );
    }

    /**
     * Build a list of entries that match the given filter.
     */
    private static void comboFilter(String enteredText, JComboBox jcb, List<String> entries) {
        List<String> entriesFiltered = new ArrayList<>();

        for (String entry : entries) {
            if (entry.toLowerCase().contains(enteredText.toLowerCase())) {
                entriesFiltered.add(entry);
            }
        }

        if (entriesFiltered.size() > 0) {
            jcb.setModel(
                    new DefaultComboBoxModel(
                            entriesFiltered.toArray()));
            jcb.setSelectedItem(enteredText);
            jcb.showPopup();
            
        } else {
            jcb.hidePopup();
        }
    }

}

【讨论】:

    猜你喜欢
    • 2013-05-01
    • 2012-12-22
    • 2014-05-06
    • 1970-01-01
    • 2020-06-26
    • 2013-10-28
    • 2010-12-04
    • 2011-08-01
    相关资源
    最近更新 更多