java 如何在文本字段内键入时列出建议

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6674462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 16:53:03  来源:igfitidea点击:

How to list suggestions to when typing inside the text field

javaswingautocompletejtextfieldautosuggest

提问by nath

Hi in my Java swing application I need to show all possible existing entries with same initial characters while user typing in a text field. Lets say user type letter 'A' in a text field which should be a country 'America' and 'Africa' would be suggestions. So that user can select one from the list. Country list resides in my database. I know how to retrieve data from DB. But I don't know how to list them and which components I should use to achieve. Can any one guide me? Or if you can provide an example, that would be great.

您好,在我的 Java Swing 应用程序中,当用户在文本字段中键入时,我需要使用相同的初始字符显示所有可能的现有条目。假设用户在文本字段中键入字母“A”,应该是“美国”和“非洲”国家/地区的建议。这样用户就可以从列表中选择一个。国家/地区列表位于我的数据库中。我知道如何从数据库中检索数据。但我不知道如何列出它们以及我应该使用哪些组件来实现。任何人都可以指导我吗?或者如果你能提供一个例子,那就太好了。

回答by Konrad Garus

You could use the autocomplete package from SwingX. Google for "swingx autocomplete" if you need more real life examples, but the simplest way is creating a JComboBoxand calling AutoCompleteDecorator.decorate(comboBox);on it.

您可以使用SwingX自动完成包。如果您需要更多现实生活中的示例,请谷歌搜索“swingx 自动完成”,但最简单的方法是创建一个JComboBox并调用AutoCompleteDecorator.decorate(comboBox);它。

回答by Harry Joy

You should try JComboBox as an autosuggest box instead of JTextField. But if you still want it to be done using JTextField then...

您应该尝试将 JComboBox 作为自动建议框而不是 JTextField。但是,如果您仍然希望使用 JTextField 完成它,那么...

  1. Make a JPanel containing list of suggestion.Initially it will be not visible.
  2. Whenever user types something search for it and add results to the list in JPanel.
  3. Show that JPanel at the bottom of textfield in upper layer of frame.
  4. Implement click event on list so that when ever user clicks on it the text is copied to textfield.
  1. 制作一个包含建议列表的 JPanel。最初它是不可见的。
  2. 每当用户键入内容时,搜索它并将结果添加到 JPanel 的列表中。
  3. 在框架上层的文本字段底部显示 JPanel。
  4. 在列表上实现单击事件,以便在用户单击它时将文本复制到文本字段。

回答by mKorbel

thereare two classes (you are needed both for correct funcionalities), Auto Complete JTextField and AutoComplete JComboBox, excelent is that you can set if is strict (allows typing if List doesn't contains ) or not

两个类(您都需要正确的功能),Auto Complete JTextField 和 AutoComplete JComboBox,优秀的是您可以设置是否严格(如果 List 不包含则允许输入)或不

回答by Cyrill

I had a similar problem:
I wanted a Textfield for free entering text, but with the possibility to suggest existing values.

我有一个类似的问题:
我想要一个用于自由输入文本的文本字段,但可以建议现有值。

I first found this post, but swingX hasn't allowed to enter text other than the suggested ones. Then I found an other post linking to this page: http://www.jroller.com/santhosh/date/20050620

我首先找到了这篇文章,但swingX 不允许输入建议文本以外的文本。然后我发现了另一个链接到这个页面的帖子:http: //www.jroller.com/santhosh/date/20050620

Some modifications and I changed from directory selection to my own Strings. Might post this here for completion and the help for later searchers:

一些修改,我从目录选择更改为我自己的字符串。可能会在此处发布以供完成并为以后的搜索者提供帮助:

He made an abstract class AutoCompleterwhich handels the events:

他创建了一个AutoCompleter处理事件的抽象类:

// @author Santhosh Kumar T - [email protected] 
public abstract class AutoCompleter{ 
    JList list = new JList(); 
    JPopupMenu popup = new JPopupMenu(); 
    JTextComponent textComp; 
    private static final String AUTOCOMPLETER = "AUTOCOMPLETER"; //NOI18N 

    public AutoCompleter(JTextComponent comp){ 
        textComp = comp; 
        textComp.putClientProperty(AUTOCOMPLETER, this); 
        JScrollPane scroll = new JScrollPane(list); 
        scroll.setBorder(null); 

        list.setFocusable( false ); 
        scroll.getVerticalScrollBar().setFocusable( false ); 
        scroll.getHorizontalScrollBar().setFocusable( false ); 

        popup.setBorder(BorderFactory.createLineBorder(Color.black)); 
        popup.add(scroll); 

        if(textComp instanceof JTextField){ 
            textComp.registerKeyboardAction(showAction, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), JComponent.WHEN_FOCUSED); 
            textComp.getDocument().addDocumentListener(documentListener); 
        }else 
            textComp.registerKeyboardAction(showAction, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK), JComponent.WHEN_FOCUSED); 

        textComp.registerKeyboardAction(upAction, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), JComponent.WHEN_FOCUSED); 
        textComp.registerKeyboardAction(hidePopupAction, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED); 

        popup.addPopupMenuListener(new PopupMenuListener(){ 
            public void popupMenuWillBecomeVisible(PopupMenuEvent e){ 
            } 

            public void popupMenuWillBecomeInvisible(PopupMenuEvent e){ 
                textComp.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); 
            } 

            public void popupMenuCanceled(PopupMenuEvent e){ 
            } 
        }); 
        list.setRequestFocusEnabled(false); 
    } 

    static Action acceptAction = new AbstractAction(){ 
        public void actionPerformed(ActionEvent e){ 
            JComponent tf = (JComponent)e.getSource(); 
            AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER); 
            completer.popup.setVisible(false); 
            completer.acceptedListItem((String)completer.list.getSelectedValue()); 
        } 
    }; 

    DocumentListener documentListener = new DocumentListener(){ 
        public void insertUpdate(DocumentEvent e){ 
            showPopup(); 
        } 

        public void removeUpdate(DocumentEvent e){ 
            showPopup(); 
        } 

        public void changedUpdate(DocumentEvent e){} 
    }; 

    private void showPopup(){ 
        popup.setVisible(false); 
        if(textComp.isEnabled() && updateListData() && list.getModel().getSize()!=0){ 
            if(!(textComp instanceof JTextField)) 
                textComp.getDocument().addDocumentListener(documentListener); 
            textComp.registerKeyboardAction(acceptAction, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_FOCUSED); 
            int size = list.getModel().getSize(); 
            list.setVisibleRowCount(size<10 ? size : 10); 

            int x = 0; 
            try{ 
                int pos = Math.min(textComp.getCaret().getDot(), textComp.getCaret().getMark()); 
                x = textComp.getUI().modelToView(textComp, pos).x; 
            } catch(BadLocationException e){ 
                // this should never happen!!! 
                e.printStackTrace(); 
            } 
            popup.show(textComp, x, textComp.getHeight()); 
        }else 
            popup.setVisible(false); 
        textComp.requestFocus(); 
    } 

    static Action showAction = new AbstractAction(){ 
        public void actionPerformed(ActionEvent e){ 
            JComponent tf = (JComponent)e.getSource(); 
            AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER); 
            if(tf.isEnabled()){ 
                if(completer.popup.isVisible()) 
                    completer.selectNextPossibleValue(); 
                else 
                    completer.showPopup(); 
            } 
        } 
    }; 

    static Action upAction = new AbstractAction(){ 
        public void actionPerformed(ActionEvent e){ 
            JComponent tf = (JComponent)e.getSource(); 
            AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER); 
            if(tf.isEnabled()){ 
                if(completer.popup.isVisible()) 
                    completer.selectPreviousPossibleValue(); 
            } 
        } 
    }; 

    static Action hidePopupAction = new AbstractAction(){ 
        public void actionPerformed(ActionEvent e){ 
            JComponent tf = (JComponent)e.getSource(); 
            AutoCompleter completer = (AutoCompleter)tf.getClientProperty(AUTOCOMPLETER); 
            if(tf.isEnabled()) 
                completer.popup.setVisible(false); 
        } 
    }; 

    /** 
     * Selects the next item in the list.  It won't change the selection if the 
     * currently selected item is already the last item. 
     */ 
    protected void selectNextPossibleValue(){ 
        int si = list.getSelectedIndex(); 

        if(si < list.getModel().getSize() - 1){ 
            list.setSelectedIndex(si + 1); 
            list.ensureIndexIsVisible(si + 1); 
        } 
    } 

    /** 
     * Selects the previous item in the list.  It won't change the selection if the 
     * currently selected item is already the first item. 
     */ 
    protected void selectPreviousPossibleValue(){ 
        int si = list.getSelectedIndex(); 

        if(si > 0){ 
            list.setSelectedIndex(si - 1); 
            list.ensureIndexIsVisible(si - 1); 
        } 
    } 

    // update list model depending on the data in textfield 
    protected abstract boolean updateListData(); 

    // user has selected some item in the list. update textfield accordingly... 
    protected abstract void acceptedListItem(String selected); 
}

And an Instance to handle the Content of the PopUp:

还有一个实例来处理弹出窗口的内容:

// @author Santhosh Kumar T - [email protected] 
public class FileAutoCompleter extends AutoCompleter{ 
    public FileAutoCompleter(JTextComponent comp){ 
        super(comp); 
    } 

    protected boolean updateListData(){ 
        String value = textComp.getText(); 
        int index1 = value.lastIndexOf('\'); 
        int index2 = value.lastIndexOf('/'); 
        int index = Math.max(index1, index2); 
        if(index==-1) 
            return false; 
        String dir = value.substring(0, index+1); 
        final String prefix = index==value.length()-1 ? null : value.substring(index + 1).toLowerCase(); 
        String[] files = new File(dir).list(new FilenameFilter(){ 
            public boolean accept(File dir, String name){ 
                return prefix!=null ? name.toLowerCase().startsWith(prefix) : true; 
            } 
        }); 
        if(files == null){ 
            list.setListData(new String[0]); 
            return true; 
        } else{ 
            if(files.length==1 && files[0].equalsIgnoreCase(prefix)) 
                list.setListData(new String[0]); 
            else 
                list.setListData(files); 
            return true; 
        } 
    } 

    protected void acceptedListItem(String selected){ 
        if(selected==null) 
            return; 

        String value = textComp.getText(); 
        int index1 = value.lastIndexOf('\'); 
        int index2 = value.lastIndexOf('/'); 
        int index = Math.max(index1, index2); 
        if(index==-1) 
            return; 
        int prefixlen = textComp.getDocument().getLength()-index-1; 
        try{ 
            textComp.getDocument().insertString(textComp.getCaretPosition(), selected.substring(prefixlen), null); 
        } catch(BadLocationException e){ 
            e.printStackTrace(); 
        } 
    } 
}

All is called in the program with

所有在程序中调用

new FileAutoCompleter(yourJTextField);