2013-01-06 93 views
24

我想创建一个自动建议文本框,它将在每个键释放事件中查询数据库。 这部分很简单,但我想给它很好的视觉效果。类似于我们在Facebook等网站中看到的自动提示文本框。使用下拉列表在Java中创建自动填充文本框

如何制作这样的界面?

一个天真的想法是将一个JList放置在文本框的正下方,并将其设置为可见,并在查找结果中将其显示出来。

任何更好的主意或标准的做法?

+0

[看看这个现有的答案](http://stackoverflow.com/questions/1861921/auto-complete-textbox-in-java-swing?rq=1) – atomman

+0

它没有下拉!这可以做到。问题在于如何根据结果的数量来显示可变大小的下拉菜单。 – jairaj

+0

@jairaj无论用JTextField都可以实现什么,可以很容易地转换成JComboBox。您只需将该JTextField设置为JCombobox的ComboBoxEditor,并使JComboBox可编辑。顺便说一句,我会看看SwingX已经有一个相当不错的autocomlete组件(看看谷歌) –

回答

39

@ syb0rg的答案比较容易,因为它使用了第三方库。

但是我使用的替代方法:

它使用称为AutoSuggestor的自定义类,它接受一个JTextField,其Window话要检查,背景颜色和文本颜色,并建议聚焦色类型的单词的ArrayList<String>以及不透明的价值。通过传递JTextField参考DocumentListener将被添加,这将执行检查什么单词是键入和是否显示建议,如果是的话显示什么建议的工作。当键入一个单词时,DocumentListener将触发wordTyped(String wordTyped)方法,并输入当前单词或(至少有多少单词已输入),在wordTyped(..)中将对照那些在AutoSuggestor类中的单词字典其中是的String这个基本ArrayList可以即时被设置为在下面的例子中看出:

enter image description here

(现在你将不得不使用鼠标点击你想成为自动补全的词,或使用向下横向建议和textfield and ENTER使用下移键时,选择建议。我还没有实现UP尚):

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.ArrayList; 
import javax.swing.AbstractAction; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.JWindow; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 
import javax.swing.border.LineBorder; 
import javax.swing.event.DocumentEvent; 
import javax.swing.event.DocumentListener; 

/** 
* @author David 
*/ 
public class Test { 

    public Test() { 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 


     JTextField f = new JTextField(10); 

     AutoSuggestor autoSuggestor = new AutoSuggestor(f, frame, null, Color.WHITE.brighter(), Color.BLUE, Color.RED, 0.75f) { 
      @Override 
      boolean wordTyped(String typedWord) { 

       //create list for dictionary this in your case might be done via calling a method which queries db and returns results as arraylist 
       ArrayList<String> words = new ArrayList<>(); 
       words.add("hello"); 
       words.add("heritage"); 
       words.add("happiness"); 
       words.add("goodbye"); 
       words.add("cruel"); 
       words.add("car"); 
       words.add("war"); 
       words.add("will"); 
       words.add("world"); 
       words.add("wall"); 


       setDictionary(words); 
       //addToDictionary("bye");//adds a single word 

       return super.wordTyped(typedWord);//now call super to check for any matches against newest dictionary 
      } 
     }; 

     JPanel p = new JPanel(); 

     p.add(f); 

     frame.add(p); 

     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Test(); 
      } 
     }); 
    } 
} 

class AutoSuggestor { 

    private final JTextField textField; 
    private final Window container; 
    private JPanel suggestionsPanel; 
    private JWindow autoSuggestionPopUpWindow; 
    private String typedWord; 
    private final ArrayList<String> dictionary = new ArrayList<>(); 
    private int currentIndexOfSpace, tW, tH; 
    private DocumentListener documentListener = new DocumentListener() { 
     @Override 
     public void insertUpdate(DocumentEvent de) { 
      checkForAndShowSuggestions(); 
     } 

     @Override 
     public void removeUpdate(DocumentEvent de) { 
      checkForAndShowSuggestions(); 
     } 

     @Override 
     public void changedUpdate(DocumentEvent de) { 
      checkForAndShowSuggestions(); 
     } 
    }; 
    private final Color suggestionsTextColor; 
    private final Color suggestionFocusedColor; 

    public AutoSuggestor(JTextField textField, Window mainWindow, ArrayList<String> words, Color popUpBackground, Color textColor, Color suggestionFocusedColor, float opacity) { 
     this.textField = textField; 
     this.suggestionsTextColor = textColor; 
     this.container = mainWindow; 
     this.suggestionFocusedColor = suggestionFocusedColor; 
     this.textField.getDocument().addDocumentListener(documentListener); 

     setDictionary(words); 

     typedWord = ""; 
     currentIndexOfSpace = 0; 
     tW = 0; 
     tH = 0; 

     autoSuggestionPopUpWindow = new JWindow(mainWindow); 
     autoSuggestionPopUpWindow.setOpacity(opacity); 

     suggestionsPanel = new JPanel(); 
     suggestionsPanel.setLayout(new GridLayout(0, 1)); 
     suggestionsPanel.setBackground(popUpBackground); 

     addKeyBindingToRequestFocusInPopUpWindow(); 
    } 

    private void addKeyBindingToRequestFocusInPopUpWindow() { 
     textField.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released"); 
     textField.getActionMap().put("Down released", new AbstractAction() { 
      @Override 
      public void actionPerformed(ActionEvent ae) {//focuses the first label on popwindow 
       for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) { 
        if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) { 
         ((SuggestionLabel) suggestionsPanel.getComponent(i)).setFocused(true); 
         autoSuggestionPopUpWindow.toFront(); 
         autoSuggestionPopUpWindow.requestFocusInWindow(); 
         suggestionsPanel.requestFocusInWindow(); 
         suggestionsPanel.getComponent(i).requestFocusInWindow(); 
         break; 
        } 
       } 
      } 
     }); 
     suggestionsPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Down released"); 
     suggestionsPanel.getActionMap().put("Down released", new AbstractAction() { 
      int lastFocusableIndex = 0; 

      @Override 
      public void actionPerformed(ActionEvent ae) {//allows scrolling of labels in pop window (I know very hacky for now :)) 

       ArrayList<SuggestionLabel> sls = getAddedSuggestionLabels(); 
       int max = sls.size(); 

       if (max > 1) {//more than 1 suggestion 
        for (int i = 0; i < max; i++) { 
         SuggestionLabel sl = sls.get(i); 
         if (sl.isFocused()) { 
          if (lastFocusableIndex == max - 1) { 
           lastFocusableIndex = 0; 
           sl.setFocused(false); 
           autoSuggestionPopUpWindow.setVisible(false); 
           setFocusToTextField(); 
           checkForAndShowSuggestions();//fire method as if document listener change occured and fired it 

          } else { 
           sl.setFocused(false); 
           lastFocusableIndex = i; 
          } 
         } else if (lastFocusableIndex <= i) { 
          if (i < max) { 
           sl.setFocused(true); 
           autoSuggestionPopUpWindow.toFront(); 
           autoSuggestionPopUpWindow.requestFocusInWindow(); 
           suggestionsPanel.requestFocusInWindow(); 
           suggestionsPanel.getComponent(i).requestFocusInWindow(); 
           lastFocusableIndex = i; 
           break; 
          } 
         } 
        } 
       } else {//only a single suggestion was given 
        autoSuggestionPopUpWindow.setVisible(false); 
        setFocusToTextField(); 
        checkForAndShowSuggestions();//fire method as if document listener change occured and fired it 
       } 
      } 
     }); 
    } 

    private void setFocusToTextField() { 
     container.toFront(); 
     container.requestFocusInWindow(); 
     textField.requestFocusInWindow(); 
    } 

    public ArrayList<SuggestionLabel> getAddedSuggestionLabels() { 
     ArrayList<SuggestionLabel> sls = new ArrayList<>(); 
     for (int i = 0; i < suggestionsPanel.getComponentCount(); i++) { 
      if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) { 
       SuggestionLabel sl = (SuggestionLabel) suggestionsPanel.getComponent(i); 
       sls.add(sl); 
      } 
     } 
     return sls; 
    } 

    private void checkForAndShowSuggestions() { 
     typedWord = getCurrentlyTypedWord(); 

     suggestionsPanel.removeAll();//remove previos words/jlabels that were added 

     //used to calcualte size of JWindow as new Jlabels are added 
     tW = 0; 
     tH = 0; 

     boolean added = wordTyped(typedWord); 

     if (!added) { 
      if (autoSuggestionPopUpWindow.isVisible()) { 
       autoSuggestionPopUpWindow.setVisible(false); 
      } 
     } else { 
      showPopUpWindow(); 
      setFocusToTextField(); 
     } 
    } 

    protected void addWordToSuggestions(String word) { 
     SuggestionLabel suggestionLabel = new SuggestionLabel(word, suggestionFocusedColor, suggestionsTextColor, this); 

     calculatePopUpWindowSize(suggestionLabel); 

     suggestionsPanel.add(suggestionLabel); 
    } 

    public String getCurrentlyTypedWord() {//get newest word after last white spaceif any or the first word if no white spaces 
     String text = textField.getText(); 
     String wordBeingTyped = ""; 
     if (text.contains(" ")) { 
      int tmp = text.lastIndexOf(" "); 
      if (tmp >= currentIndexOfSpace) { 
       currentIndexOfSpace = tmp; 
       wordBeingTyped = text.substring(text.lastIndexOf(" ")); 
      } 
     } else { 
      wordBeingTyped = text; 
     } 
     return wordBeingTyped.trim(); 
    } 

    private void calculatePopUpWindowSize(JLabel label) { 
     //so we can size the JWindow correctly 
     if (tW < label.getPreferredSize().width) { 
      tW = label.getPreferredSize().width; 
     } 
     tH += label.getPreferredSize().height; 
    } 

    private void showPopUpWindow() { 
     autoSuggestionPopUpWindow.getContentPane().add(suggestionsPanel); 
     autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textField.getWidth(), 30)); 
     autoSuggestionPopUpWindow.setSize(tW, tH); 
     autoSuggestionPopUpWindow.setVisible(true); 

     int windowX = 0; 
     int windowY = 0; 

     windowX = container.getX() + textField.getX() + 5; 
     if (suggestionsPanel.getHeight() > autoSuggestionPopUpWindow.getMinimumSize().height) { 
      windowY = container.getY() + textField.getY() + textField.getHeight() + autoSuggestionPopUpWindow.getMinimumSize().height; 
     } else { 
      windowY = container.getY() + textField.getY() + textField.getHeight() + autoSuggestionPopUpWindow.getHeight(); 
     } 

     autoSuggestionPopUpWindow.setLocation(windowX, windowY); 
     autoSuggestionPopUpWindow.setMinimumSize(new Dimension(textField.getWidth(), 30)); 
     autoSuggestionPopUpWindow.revalidate(); 
     autoSuggestionPopUpWindow.repaint(); 

    } 

    public void setDictionary(ArrayList<String> words) { 
     dictionary.clear(); 
     if (words == null) { 
      return;//so we can call constructor with null value for dictionary without exception thrown 
     } 
     for (String word : words) { 
      dictionary.add(word); 
     } 
    } 

    public JWindow getAutoSuggestionPopUpWindow() { 
     return autoSuggestionPopUpWindow; 
    } 

    public Window getContainer() { 
     return container; 
    } 

    public JTextField getTextField() { 
     return textField; 
    } 

    public void addToDictionary(String word) { 
     dictionary.add(word); 
    } 

    boolean wordTyped(String typedWord) { 

     if (typedWord.isEmpty()) { 
      return false; 
     } 
     //System.out.println("Typed word: " + typedWord); 

     boolean suggestionAdded = false; 

     for (String word : dictionary) {//get words in the dictionary which we added 
      boolean fullymatches = true; 
      for (int i = 0; i < typedWord.length(); i++) {//each string in the word 
       if (!typedWord.toLowerCase().startsWith(String.valueOf(word.toLowerCase().charAt(i)), i)) {//check for match 
        fullymatches = false; 
        break; 
       } 
      } 
      if (fullymatches) { 
       addWordToSuggestions(word); 
       suggestionAdded = true; 
      } 
     } 
     return suggestionAdded; 
    } 
} 

class SuggestionLabel extends JLabel { 

    private boolean focused = false; 
    private final JWindow autoSuggestionsPopUpWindow; 
    private final JTextField textField; 
    private final AutoSuggestor autoSuggestor; 
    private Color suggestionsTextColor, suggestionBorderColor; 

    public SuggestionLabel(String string, final Color borderColor, Color suggestionsTextColor, AutoSuggestor autoSuggestor) { 
     super(string); 

     this.suggestionsTextColor = suggestionsTextColor; 
     this.autoSuggestor = autoSuggestor; 
     this.textField = autoSuggestor.getTextField(); 
     this.suggestionBorderColor = borderColor; 
     this.autoSuggestionsPopUpWindow = autoSuggestor.getAutoSuggestionPopUpWindow(); 

     initComponent(); 
    } 

    private void initComponent() { 
     setFocusable(true); 
     setForeground(suggestionsTextColor); 

     addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseClicked(MouseEvent me) { 
       super.mouseClicked(me); 

       replaceWithSuggestedText(); 

       autoSuggestionsPopUpWindow.setVisible(false); 
      } 
     }); 

     getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "Enter released"); 
     getActionMap().put("Enter released", new AbstractAction() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       replaceWithSuggestedText(); 
       autoSuggestionsPopUpWindow.setVisible(false); 
      } 
     }); 
    } 

    public void setFocused(boolean focused) { 
     if (focused) { 
      setBorder(new LineBorder(suggestionBorderColor)); 
     } else { 
      setBorder(null); 
     } 
     repaint(); 
     this.focused = focused; 
    } 

    public boolean isFocused() { 
     return focused; 
    } 

    private void replaceWithSuggestedText() { 
     String suggestedWord = getText(); 
     String text = textField.getText(); 
     String typedWord = autoSuggestor.getCurrentlyTypedWord(); 
     String t = text.substring(0, text.lastIndexOf(typedWord)); 
     String tmp = t + text.substring(text.lastIndexOf(typedWord)).replace(typedWord, suggestedWord); 
     textField.setText(tmp + " "); 
    } 
} 

目前的情况是唯一可能需要的补充IMO是:

  • UP重点traversablity物品弹出自动建议盒子内,所以我们可以向上发展。

如果有任何扭结知道我会看看我能做些什么。但似乎运行良好(触摸木材)。

+1

好的一个!但是当我输入的重点从文本字段丢失。我必须再次点击文本字段才能重新开始输入。所以,对于我输入的每个字符,我都必须强调文本字段和类型。你有没有遇到这个问题?如果是的话,你有修好吗? – arunram

+0

@arunram同样的事情发生在我身上。该代码在Windows 7上运行得很完美,但没有在Machintosh OS X Yosemite(10.10.2)上运行。我仍然试图解决这个问题,但我不是专家,所以这可能需要很长时间。没有承诺,但我会尽我所能。 – panoet

+0

我最喜欢这个解决方案。其他人更优雅,但这个更容易破解和学习 –

25

一个很简单的方法就是使用自动完成的GlazedList实现。起床和跑步非常容易。你可以找到它here

可以安装自动完成上一个JComboBox,只有一行的釉面代码,就像这样:

JComboBox comboBox = new JComboBox(); 
Object[] elements = new Object[] {"Cat", "Dog", "Lion", "Mouse"}; 
AutoCompleteSupport.install(comboBox, GlazedLists.eventListOf(elements)); 

而且SwingX支持自动完成,可能会更容易比GlazedList使用。你用SwingX写的全部是AutoCompleteDecorator.decorate(comboBox);

+3

“你用SwingX编写的所有代码都是AutoCompleteDecorator.decorate(comboBox);”很好的回答!!!为什么我只在4天后才发现这个问题? – Blocked

+0

我得到这个错误代码:'必须从Swing Event Dispatch Thread'访问'AutoCompleteSupport'。 –

+0

我找不到jar文件GlazedLists.eventListOf可以帮我找到一个jar文件。 – heshjse

2

要使用TextAutoCompleter类,你需要下载一个jar文件AutoCompleter.jar并将其添加到您的项目的库文件夹,这里是链接下载:http://download1689.mediafire.com/4grrthscpsug/7pwzgefiomu392o/AutoCompleter.jar -Nawin

//在主类写下面的代码

package autocomplete; 

import com.mxrck.autocompleter.TextAutoCompleter; 
import java.sql.SQLException; 
import javax.swing.JFrame; 
import javax.swing.JTextField; 


public class AutoComplete { 
    JFrame f=new JFrame(); 
    JTextField t1; 
AutoComplete() throws ClassNotFoundException, SQLException{ 

    f.setSize(500,500); 
    f.setLocation(500,100); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    f.setLayout(null); 
    f.setVisible(true); 


    t1=new JTextField(); 
    t1.setBounds(50,80,200,20); 
    f.add(t1); 


    TextAutoCompleter complete=new TextAutoCompleter(t1); 
    DBConn conn=new DBConn(); 
     conn.connection(); 
     conn.retrieve(); 
    while(conn.rs.next()){ 

     complete.addItem(conn.rs.getString("number")); 
    } 


} 


    public static void main(String[] args) throws ClassNotFoundException, 
    SQLException{   

     new AutoComplete(); 
    } 

} 


//Create seperate class for database connection and write the following code 


package autocomplete; 

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement; 


public class DBConn { 

    Connection con; ResultSet rs;PreparedStatement stat; 

public void connection() throws ClassNotFoundException, SQLException{ 
    String url="jdbc:mysql://localhost:3306/"; 
    String driver="com.mysql.jdbc.Driver"; 
    String db="demo"; 
    String username="root"; 
    String password="root"; 
    stat =null; 

     Class.forName(driver); 
     con=(Connection)DriverManager.getConnection 
     (url+db,username,password);    
     System.out.println("Connecttion SuccessFul"); 
} 

public void retrieve() throws SQLException{ 

    Statement stmt=con.createStatement(); 
    String query="select number from phone"; 
    rs = stmt.executeQuery(query); 

    System.out.println("retrieve succesfully"); 

} 

}

+0

khawatiwada感谢您的建议。我正在网上冲浪,偶然发现了这一点。我想在一个HTTP服务器(如WAMP)中使用它,我将通过RESTFul API调用我的字符串。你清楚的例子中只有一个问题:我如何使用在文本字段中输入的字符串作为serach参数?上面的例子对我来说真的不太清楚。谢谢 – Maximum86

1

我想自动完成对我的AVR汇编IDE的编辑器,以便I wrote an implementation的作品就像在Eclipse(CTRL-SPACE激活自动完成,滴,倒升带滚动条,光标键+鼠标导航)。它没有外部依赖关系,只是一个类。它应该适用于所有JTextComponent子类;您可以在src/test文件夹中找到一个使用示例。

0

将此行添加到第一个答案的private void addKeyBindingToRequestFocusInPopUpWindow()以实现UP键。他的回答很完美。

//here I have to do my code for up key 
    //--------------------------------------------------------------------- 
    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    textField.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "Up released"); 
    textField.getActionMap().put("Up released", new AbstractAction() { 
     @Override 
     public void actionPerformed(ActionEvent ae) {//focuses the first label on popwindow 
      for (int i = suggestionsPanel.getComponentCount()-1; i >=0; i--) { 
       if (suggestionsPanel.getComponent(i) instanceof SuggestionLabel) { 
        ((SuggestionLabel) suggestionsPanel.getComponent(i)).setFocused(true); 
        autoSuggestionPopUpWindow.toFront(); 
        autoSuggestionPopUpWindow.requestFocusInWindow(); 
        suggestionsPanel.requestFocusInWindow(); 
        suggestionsPanel.getComponent(i).requestFocusInWindow(); 
        break; 
       } 
      } 
     } 
    }); 

    suggestionsPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "Up released"); 
    suggestionsPanel.getActionMap().put("Up released", new AbstractAction() { 
     //######int lastFocusableIndex = 0; 
     int lastFocusableIndex = 0; 
     //lastFocusableIndex=lastFocusableIndex___; 
     @Override 
     public void actionPerformed(ActionEvent ae) {//allows scrolling of labels in pop window (I know very hacky for now :)) 

      ArrayList<SuggestionLabel> sls = getAddedSuggestionLabels(); 
      int max = sls.size(); 
      lastFocusableIndex=lastFocusableIndex___; 

      System.out.println("UP UP UP UP");//***// 
      System.out.println("max = "+String.valueOf(max));//***// 
      System.out.println("lastFocusableIndex = "+String.valueOf(lastFocusableIndex));//***// 
      System.out.println("UP UP UP UP");//***// 

      if (max > 1) {//more than 1 suggestion 
       for (int i = max-1; i >=0; i--) { 
        SuggestionLabel sl = sls.get(i); 
        if (sl.isFocused()) { 
         if (lastFocusableIndex == 0) { 
          lastFocusableIndex = max - 1; 
          lastFocusableIndex___=lastFocusableIndex; 
          sl.setFocused(false); 
          autoSuggestionPopUpWindow.setVisible(false); 
          setFocusToTextField(); 
          checkForAndShowSuggestions();//fire method as if document listener change occured and fired it 

         } else { 
          sl.setFocused(false); 
          lastFocusableIndex = i; 
          lastFocusableIndex___=lastFocusableIndex; 
         } 
        } else if (lastFocusableIndex > i) { 
         if (i < max) { 
          sl.setFocused(true); 
          autoSuggestionPopUpWindow.toFront(); 
          autoSuggestionPopUpWindow.requestFocusInWindow(); 
          suggestionsPanel.requestFocusInWindow(); 
          suggestionsPanel.getComponent(i).requestFocusInWindow(); 
          lastFocusableIndex = i; 
          lastFocusableIndex___=lastFocusableIndex; 
          break; 
         } 
        } 
       } 
      } else {//only a single suggestion was given 
       autoSuggestionPopUpWindow.setVisible(false); 
       setFocusToTextField(); 
       checkForAndShowSuggestions();//fire method as if document listener change occured and fired it 
      } 
     } 
    }); 
0

,我在一个项目上使用的工作计算策略是把一个JTextField上的JComboBox的顶部,使底层组合框打开,你使用的文档侦听器键入到JTextField中。您可能需要一个自定义组合框模型,以便更有效地更改项目,因为默认模型我认为只允许一次添加一个项目,这可能会影响性能。打开组合框我认为有一种方法来显示它,如果你得到它的用户界面。当我尝试在打开项目时尝试更改项目时,遇到了几个滚动错误,因此您可能需要关闭它,更改项目并重新显示。对于键盘的东西,您可以捕获JTextField中的键盘按键,并适当地调用JComboBox。