Реализация автозаполнения в Java - я делаю это правильно? [дубликат]

этот вопрос уже есть ответ здесь:

алгоритм

  1. старт
  2. введите название города - частичное или полное
  3. если пользователь нажимает enter, возьмите текст из JTextField
  4. начать поиск грубой силы.
  5. если совпадения найдены, поместите их в Vector и поместите его в JList
  6. если совпадение не найдено, добавьте String "не найдено совпадений" в Vector
  7. дисплей JWindow пользователю, содержащему результаты
  8. остановка

код:

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() на JWindow на JList и JScrollPane но проблема не пойдет.
Я хочу, чтобы он соответствовал размеру украшенного JFrame несмотря ни на что

4 ответов


редактировать

в любом случае, так что в основном мне придется вручную создать список всех города, которые должны быть поддержаны правильно ?? ВХ @маленький ребенок

  • эта идея может быть довольно легко, вы можете поставить JTable до JWindow

  • С Column,

  • без JTableHeader

  • добавить RowSorter (см. Пример кода в учебнике)

  • затем все шаги сделаны : -), больше ничего не требуется (возможно, бонус для изменения Background of JTextField в случае, если RowFilter не возвращает совпадений, добавить setVisible для всплывающего окна из DocumentListener (обязательно проверьте на !isVisible))


вы должны использовать jcombobox в, и для автозаполнения прочитайте в этой статье.


вам нужно использовать ширину 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: просто для лучшей эстетики попробуйте использовать некоторый макет, чтобы текстовое поле заполнило всю ширину.


одним из решений было бы изменить 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);
    }