在 Java 中实现自动完成 - 我做得对吗?
Algorithm
- Start
- Input a city name - partial or complete
- If the user hits enter , take the text from
JTextField - Begin brute force search.
- If the matches are found, put them in a
Vectorand put it in aJList - If no match is found, add a
String"No Match Found" inVector - Display
JWindowto user containing the results - Stop
Code:
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() == '
'){
initiateSearch(city.getText());
}
}
@Override
public void keyReleased(KeyEvent e){
}
}
//------------------------------------------------------------------------------
}
Output
Problem
The size of the JWindow displaying the results (which is a JList in a JScrollPane) changes based on the results - if the city name is small, JWindow is small, if the city name is big, JWindow is big.
I have tried every possible combination. I tried using setPreferredDimension() of the JWindow, the JList and JScrollPane but the issue won't go.
I want it to match the size of the decorated JFrame no matter what
JListorJComboBoxdoesn't returns properPreferredSize, have to set this value, use JList.setPrototypeCellValue() withpack()forJWindow(must be packed after any changes) and or with JList.setVisibleRowCount(), then value returnsgetPreferredScrollableViewportSize()forJListinJScrollPanedon't to use
KeyListener, useDocumentListener(chars can be inserted from system clipboard) forJTextComponentsdon't to reinvent the wheel, use AutoComplete JComboBox / JTextField, you can to redirect / returns result from matches to the popup
JWindow/ undecoratedJDialog(quite the best workaround for popup recycle)
EDIT
Anyways so basically I will have to manually create a list of all the cities that are to be supported right ?? bx @Little Child
this idea could be quite easy, you can to put
JTableto theJWindowwith one
Column,without
JTableHeaderadd there RowSorter (see code example in tutorial)
then every steps are done :-), nothing else is required there (maybe bonus to change
BackgroundofJTextFieldin the case thatRowFilterreturns no matches, addsetVisiblefor popup window fromDocumentListener(be sure to test for!isVisible))
相关文章