用Java实现自动完成 - 我做得对吗?

时间:2013-02-13 08:19:20

标签: java swing autocomplete jframe jwindow

算法

  1. 开始
  2. 输入城市名称 - 部分或完整
  3. 如果用户点击进入,请从JTextField
  4. 获取文字
  5. 开始暴力搜索。
  6. 如果找到匹配项,请将其放入Vector并将其放入JList
  7. 如果未找到匹配项,请在String
  8. 中添加Vector“找不到匹配项”
  9. 向包含结果的用户显示JWindow
  10. 停止
  11. 代码:

    package test;
    import javax.swing.*;
    
    import java.awt.Dimension;
    import java.awt.event.*;
    import java.util.Vector;
    
    public class AutoCompleteTest extends JFrame{
        JTextField city = new JTextField(10);
        String enteredName = null;
        String[] cities = {"new jersey","new hampshire",
                "sussex","essex","london","delhi","new york"};
        JList list = new JList();
        JScrollPane pane = new JScrollPane();
        ResultWindow r = new ResultWindow();
    //------------------------------------------------------------------------------
        public static void main(String[] args) {
            new AutoCompleteTest();
        }
    //------------------------------------------------------------------------------
        public AutoCompleteTest(){
            setLayout(new java.awt.FlowLayout());
            setVisible(true);
            add(city);
    //      add(pane);
            pack();
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            city.addKeyListener(new TextHandler());
        }
    //------------------------------------------------------------------------------
        public void initiateSearch(String lookFor){
            Vector<String> matches = new Vector<>();
            lookFor = lookFor.toLowerCase();
            for(String each : cities){
                if(each.contains(lookFor)){
                    matches.add(each);
                    System.out.println("Match: " + each);
                }
            }
            this.repaint();
    
            if(matches.size()!=0){
                list.setListData(matches);
                r.searchResult = list;
                r.pane = pane;
                r.initiateDisplay();
            }else{
                matches.add("No Match Found");
                list.setListData(matches);
                r.searchResult = list;
                r.pane = pane;
                r.initiateDisplay();
            }
    
        }
    //------------------------------------------------------------------------------
        public class ResultWindow extends JWindow{
            public JScrollPane pane;
            public JList searchResult;
    //------------------------------------------------------------------------------
            public ResultWindow(){
    
            }
    //------------------------------------------------------------------------------
            public void initiateDisplay(){
                pane.setViewportView(searchResult);
                add(pane);
                pack();
                this.setLocation(AutoCompleteTest.this.getX() + 2, 
                        AutoCompleteTest.this.getY()+
                        AutoCompleteTest.this.getHeight());
    
    //          this.setPreferredSize(city.getPreferredSize());
                this.setVisible(true);
            }
        }
    //------------------------------------------------------------------------------
    
        class TextHandler implements KeyListener{
            @Override
            public void keyTyped(KeyEvent e){
    
            }
    
            @Override
            public void keyPressed(KeyEvent e){
                if(r.isVisible()){
                    r.setVisible(false);
                }
                if(e.getKeyChar() == '\n'){
                    initiateSearch(city.getText());
                }
            }
    
            @Override
            public void keyReleased(KeyEvent e){
    
            }
        }
    //------------------------------------------------------------------------------
    }
    

    输出

    enter image description here

    问题

    显示结果的JWindow的大小(JList中的JScrollPane)会根据结果发生变化 - 如果城市名称很小,JWindow很小,如果城市名称很大,JWindow很大。

    我尝试了所有可能的组合。我尝试使用setPreferredDimension()JWindowJList的{​​{1}},但问题不会发生。
    我希望它与装饰JScrollPane的大小相匹配,无论是什么

4 个答案:

答案 0 :(得分:7)

修改

  

无论如何基本上我将不得不手动创建所有的列表   要得到支持的城市吗? bx @Little Child

  • 这个想法可能很简单,你可以放JTable to the JWindow

  • 只有一个JScrollPane

  • 没有Column

  • 添加RowSorter(参见教程中的代码示例)

  • 然后每个步骤都完成了:-),那里不需要任何其他内容(如果JTableHeader没有返回任何匹配项,可能会更改Background JTextField的奖励,添加来自RowFilter的弹出窗口setVisible(请务必测试DocumentListener))

答案 1 :(得分:1)

每次启动搜索时都需要使用JFrame的宽度,并使用它来计算列表的宽度。

只需像这样更改initiateSearch()函数:

public void initiateSearch(String lookFor){

    //add the following two statements to set the width of the list.
    int newWidth = AutoCompleteTest.this.getSize().width;        
    list.setPreferredSize(new Dimension(newWidth, list.getPreferredSize().height));

        Vector<String> matches = new Vector<String>();
        lookFor = lookFor.toLowerCase();
        for(String each : cities){
            if(each.contains(lookFor)){
                matches.add(each);
                System.out.println("Match: " + each);
            }
        }
        this.repaint();

        if(matches.size()!=0){
            list.setListData(matches);
            r.searchResult = list;
            r.pane = pane;
            r.initiateDisplay();
        }else{
            matches.add("No Match Found");
            list.setListData(matches);
            r.searchResult = list;
            r.pane = pane;
            r.initiateDisplay();
        }

    }

以下是示例输出:

small size

enter image description here

PS:为了更好的美学,尝试使用一些布局使文本字段填满整个宽度。

答案 2 :(得分:1)

您应该使用JComboBox,并且要自动完成,请阅读this article

答案 3 :(得分:1)

一种解决方案是将initiateDisplay()更改为:

public void initiateDisplay()
    {
        this.pane.setViewportView(this.searchResult);
        this.add(this.pane);
        this.pack();
        this.setLocation(AutoCompleteTest.this.getX() + 2, AutoCompleteTest.this.getY()
                + AutoCompleteTest.this.getHeight());

        int padding = 5;
        int height = this.searchResult.getModel().getSize()
                * AutoCompleteTest.this.city.getSize().height;
        int windowWidth = AutoCompleteTest.this.getSize().width;

        this.setSize(windowWidth, height);
        this.setVisible(true);
    }