在 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
Vector
and put it in aJList
- If no match is found, add a
String
"No Match Found" inVector
- Display
JWindow
to 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
JList
orJComboBox
doesn'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()
forJList
inJScrollPane
don't to use
KeyListener
, useDocumentListener
(chars can be inserted from system clipboard) forJTextComponents
don'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
JTable
to theJWindow
with one
Column
,without
JTableHeader
add there RowSorter (see code example in tutorial)
then every steps are done :-), nothing else is required there (maybe bonus to change
Background
ofJTextField
in the case thatRowFilter
returns no matches, addsetVisible
for popup window fromDocumentListener
(be sure to test for!isVisible
))
相关文章