Primeiro você faz uma JComboBox normal. Se ela for Strict, você marca ela como “setEditable(false)”. Se ela não for strict, vc não faz isso.
Depois, você usa o AutoCompleteDecorator na sua ComboBox. E pronto!
ViniGodoy
Se vc quiser, pode usar essa classe que facilita esse processo:
importjava.awt.Color;importjava.awt.event.FocusEvent;importjava.awt.event.FocusListener;importjava.util.Collection;importjava.util.Vector;importjavax.swing.ComboBoxModel;importjavax.swing.JComboBox;importjavax.swing.UIManager;importjavax.swing.text.JTextComponent;publicclassAutoCompleteComboBoxextendsJComboBox{publicAutoCompleteComboBox(){super();initialize(false);}publicAutoCompleteComboBox(ComboBoxModelaModel){super(aModel);initialize(false);}publicAutoCompleteComboBox(Object...items){super(items);initialize(false);}publicAutoCompleteComboBox(Collection<?>items){super(newVector<Object>(items));initialize(false);}publicAutoCompleteComboBox(booleaneditable){super();initialize(editable);}publicAutoCompleteComboBox(ComboBoxModelaModel,booleaneditable){super(aModel);initialize(editable);}publicAutoCompleteComboBox(Collection<?>items,booleaneditable){super(newVector<Object>(items));initialize(editable);}privatevoidinitialize(booleaneditable){setEditable(editable);AutoCompleteDecorator.decorate(this);finalColorgray=getBackground();finalColorgreen=UIManager.getColor("ComboBox.selectionBackground");// final Color selection = ((JTextComponent)// getEditor().getEditorComponent()).getSelectionColor();getEditor().getEditorComponent().setBackground(gray);((JTextComponent)getEditor().getEditorComponent()).setSelectionColor(gray);((JTextComponent)getEditor().getEditorComponent()).setCaretColor(Color.white);((JTextComponent)getEditor().getEditorComponent()).setForeground(((JTextComponent)getEditor().getEditorComponent()).getSelectedTextColor());getEditor().getEditorComponent().addFocusListener(newFocusListener(){publicvoidfocusGained(FocusEvente){getEditor().getEditorComponent().setBackground(green);((JTextComponent)getEditor().getEditorComponent()).setSelectionColor(green);}publicvoidfocusLost(FocusEvente){getEditor().getEditorComponent().setBackground(gray);((JTextComponent)getEditor().getEditorComponent()).setSelectionColor(gray);}});}@OverridepublicvoidsetEnabled(booleanb){super.setEnabled(b);getEditor().getEditorComponent().setBackground(getBackground());}}
ViniGodoy
Nós também fizemos algumas correções no Decorator do SwingX:
importjava.awt.event.ActionEvent;importjava.awt.event.FocusAdapter;importjava.awt.event.FocusEvent;importjava.awt.event.KeyAdapter;importjava.awt.event.KeyEvent;importjava.awt.event.KeyListener;importjava.beans.PropertyChangeEvent;importjava.beans.PropertyChangeListener;importjavax.swing.Action;importjavax.swing.ActionMap;importjavax.swing.ComboBoxEditor;importjavax.swing.InputMap;importjavax.swing.JComboBox;importjavax.swing.KeyStroke;importjavax.swing.UIManager;importjavax.swing.text.DefaultEditorKit;importjavax.swing.text.JTextComponent;importjavax.swing.text.TextAction;importorg.jdesktop.swingx.autocomplete.AbstractAutoCompleteAdaptor;importorg.jdesktop.swingx.autocomplete.AutoCompleteComboBoxEditor;importorg.jdesktop.swingx.autocomplete.AutoCompleteDocument;importorg.jdesktop.swingx.autocomplete.ComboBoxAdaptor;importorg.jdesktop.swingx.autocomplete.ObjectToStringConverter;importorg.jdesktop.swingx.autocomplete.workarounds.AquaLnFPopupLocationFix;/** * This class contains only static utility methods that can be used to set up * automatic completion for some Swing components. * <p> * Usage examples: * </p> * <p> * * <pre><code> * JComboBox comboBox = [...]; * AutoCompleteDecorator.<b>decorate</b>(comboBox); * * List items = [...]; * JTextField textField = [...]; * AutoCompleteDecorator.<b>decorate</b>(textField, items); * * JList list = [...]; * JTextField textField = [...]; * AutoCompleteDecorator.<b>decorate</b>(list, textField); * </code></pre> * * </p> * * @author Thomas Bierhance */publicclassAutoCompleteDecorator{/** * Enables automatic completion for the given JComboBox. The automatic * completion will be strict (only items from the combo box can be selected) * if the combo box is not editable. * * @param comboBox a combo box */publicstaticvoiddecorate(finalJComboBoxcomboBox){decorate(comboBox,ObjectToStringConverter.DEFAULT_IMPLEMENTATION);}/** * Enables automatic completion for the given JComboBox. The automatic * completion will be strict (only items from the combo box can be selected) * if the combo box is not editable. * * @param comboBox a combo box * @param stringConverter the converter used to transform items to strings */publicstaticvoiddecorate(finalJComboBoxcomboBox,finalObjectToStringConverterstringConverter){booleanstrictMatching=!comboBox.isEditable();// has to be editablecomboBox.setEditable(true);// fix the popup locationAquaLnFPopupLocationFix.install(comboBox);// configure the text component=editor componentJTextComponenteditorComponent=(JTextComponent)comboBox.getEditor().getEditorComponent();finalAbstractAutoCompleteAdaptoradaptor=newComboBoxAdaptor(comboBox);finalAutoCompleteDocumentdocument=newAutoCompleteDocument(adaptor,strictMatching,stringConverter);decorate(editorComponent,document,adaptor);// show the popup list when the user presses a keyfinalKeyListenerkeyListener=newKeyAdapter(){@OverridepublicvoidkeyPressed(KeyEventkeyEvent){// don't popup on action keys (cursor movements, etc...)if(keyEvent.isActionKey())return;// don't popup if the combobox isn't visible anywayif(comboBox.isDisplayable()&&!comboBox.isPopupVisible()){intkeyCode=keyEvent.getKeyCode();// don't popup when the user hits shift,ctrl or altif(keyCode==KeyEvent.VK_SHIFT||keyCode==KeyEvent.VK_CONTROL||keyCode==KeyEvent.VK_ALT)return;// don't popup when the user hits escape (see issue #311)if(keyCode==KeyEvent.VK_ESCAPE||keyCode==KeyEvent.VK_ENTER)return;if(keyEvent.isAltDown()||keyEvent.isControlDown())return;comboBox.setPopupVisible(true);}}};editorComponent.addKeyListener(keyListener);if(stringConverter!=ObjectToStringConverter.DEFAULT_IMPLEMENTATION){comboBox.setEditor(newAutoCompleteComboBoxEditor(comboBox.getEditor(),stringConverter));}// Changing the l&f can change the combobox' editor which in turn// would not be autocompletion-enabled. The new editor needs to be// set-up.comboBox.addPropertyChangeListener("editor",newPropertyChangeListener(){publicvoidpropertyChange(PropertyChangeEvente){ComboBoxEditoreditor=(ComboBoxEditor)e.getNewValue();if(editor!=null&&editor.getEditorComponent()!=null){if(!(editorinstanceofAutoCompleteComboBoxEditor)&&stringConverter!=ObjectToStringConverter.DEFAULT_IMPLEMENTATION){comboBox.setEditor(newAutoCompleteComboBoxEditor(editor,stringConverter));// Don't do the decorate step here because// calling setEditor will trigger// the propertychange listener a second time,// which will do the decorate// and addKeyListener step.}else{decorate((JTextComponent)editor.getEditorComponent(),document,adaptor);editor.getEditorComponent().addKeyListener(keyListener);}}}});}/** * Decorates a given text component for automatic completion using the given * AutoCompleteDocument and AbstractAutoCompleteAdaptor. * * @param textComponent a text component that should be decorated * @param document the AutoCompleteDocument to be installed on the text * component * @param adaptor the AbstractAutoCompleteAdaptor to be used */publicstaticvoiddecorate(JTextComponenttextComponent,AutoCompleteDocumentdocument,finalAbstractAutoCompleteAdaptoradaptor){// install the document on the text componenttextComponent.setDocument(document);// mark entire text when the text component gains focus// otherwise the last mark would have been retained which is quiet// confusingtextComponent.addFocusListener(newFocusAdapter(){@OverridepublicvoidfocusGained(FocusEvente){adaptor.markEntireText();}});// Tweak some key bindingsInputMapeditorInputMap=textComponent.getInputMap();if(document.isStrictMatching()){// move the selection to the left on VK_BACK_SPACEeditorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE,0),DefaultEditorKit.selectionBackwardAction);// ignore VK_DELETE and CTRL+VK_X and beep instead when strict// matchingeditorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DELETE,0),errorFeedbackAction);editorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X,java.awt.event.InputEvent.CTRL_DOWN_MASK),errorFeedbackAction);}else{ActionMapeditorActionMap=textComponent.getActionMap();// leave VK_DELETE and CTRL+VK_X as is// VK_BACKSPACE will move the selection to the left if the selected// item is in the list// it will delete the previous character otherwiseeditorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE,0),"nonstrict-backspace");editorActionMap.put("nonstrict-backspace",newNonStrictBackspaceAction(editorActionMap.get(DefaultEditorKit.deletePrevCharAction),editorActionMap.get(DefaultEditorKit.selectionBackwardAction),adaptor));}}staticclassNonStrictBackspaceActionextendsTextAction{Actionbackspace;ActionselectionBackward;AbstractAutoCompleteAdaptoradaptor;publicNonStrictBackspaceAction(Actionbackspace,ActionselectionBackward,AbstractAutoCompleteAdaptoradaptor){super("nonstrict-backspace");this.backspace=backspace;this.selectionBackward=selectionBackward;this.adaptor=adaptor;}publicvoidactionPerformed(ActionEvente){if(adaptor.listContainsSelectedItem()){selectionBackward.actionPerformed(e);}else{backspace.actionPerformed(e);}}}/** * A TextAction that provides an error feedback for the text component that * invoked the action. The error feedback is most likely a "beep". */staticObjecterrorFeedbackAction=newTextAction("provide-error-feedback"){publicvoidactionPerformed(ActionEvente){UIManager.getLookAndFeel().provideErrorFeedback(getTextComponent(e));}};}
brlima
Quais correções?
ViniGodoy
Fizemos uns ajustes para ele trabalhar bem na JTable. Ele tinha uns problemas ao se pressionar ESC ou quando vc clicava no scroll enquanto o editor estava selecionado.
Mas agora nem estamos usando mais esse componente. Fizemos um novo combobox que, além do autocompletion, filtra também o seu interior. Tem até suporte a wildcards como *Product.
raci0nal
ViniGodoy,
Por acaso você não pode disponibilizar a parte do Filter do seu código?
Implementei um JComboBox com uma JTable como CellRenderer e estou tentando aplicar um filtro nos resultados disparando através do keyReleased do ComboEditor.
Porém, não estou conseguindo chegar a um resultado.
Obrigado.
ViniGodoy:
Fizemos uns ajustes para ele trabalhar bem na JTable. Ele tinha uns problemas ao se pressionar ESC ou quando vc clicava no scroll enquanto o editor estava selecionado.
Mas agora nem estamos usando mais esse componente. Fizemos um novo combobox que, além do autocompletion, filtra também o seu interior. Tem até suporte a wildcards como *Product.
ViniGodoy
Não dispare eventos através do comboeditor. O comboeditor é um JTextField, logo tem um Document associado. Você deve alterar esse Document. Vou ver se ajeito o código e posto aqui.
hum, essa nunca usei, mas o nome do pacote ali não é dos melhores…
habinovich
ViniGodoy:
Nós também fizemos algumas correções no Decorator do SwingX:
importjava.awt.event.ActionEvent;importjava.awt.event.FocusAdapter;importjava.awt.event.FocusEvent;importjava.awt.event.KeyAdapter;importjava.awt.event.KeyEvent;importjava.awt.event.KeyListener;importjava.beans.PropertyChangeEvent;importjava.beans.PropertyChangeListener;importjavax.swing.Action;importjavax.swing.ActionMap;importjavax.swing.ComboBoxEditor;importjavax.swing.InputMap;importjavax.swing.JComboBox;importjavax.swing.KeyStroke;importjavax.swing.UIManager;importjavax.swing.text.DefaultEditorKit;importjavax.swing.text.JTextComponent;importjavax.swing.text.TextAction;importorg.jdesktop.swingx.autocomplete.AbstractAutoCompleteAdaptor;importorg.jdesktop.swingx.autocomplete.AutoCompleteComboBoxEditor;importorg.jdesktop.swingx.autocomplete.AutoCompleteDocument;importorg.jdesktop.swingx.autocomplete.ComboBoxAdaptor;importorg.jdesktop.swingx.autocomplete.ObjectToStringConverter;importorg.jdesktop.swingx.autocomplete.workarounds.AquaLnFPopupLocationFix;/** * This class contains only static utility methods that can be used to set up * automatic completion for some Swing components. * <p> * Usage examples: * </p> * <p> * * <pre><code> * JComboBox comboBox = [...]; * AutoCompleteDecorator.<b>decorate</b>(comboBox); * * List items = [...]; * JTextField textField = [...]; * AutoCompleteDecorator.<b>decorate</b>(textField, items); * * JList list = [...]; * JTextField textField = [...]; * AutoCompleteDecorator.<b>decorate</b>(list, textField); * </code></pre> * * </p> * * @author Thomas Bierhance */publicclassAutoCompleteDecorator{/** * Enables automatic completion for the given JComboBox. The automatic * completion will be strict (only items from the combo box can be selected) * if the combo box is not editable. * * @param comboBox a combo box */publicstaticvoiddecorate(finalJComboBoxcomboBox){decorate(comboBox,ObjectToStringConverter.DEFAULT_IMPLEMENTATION);}/** * Enables automatic completion for the given JComboBox. The automatic * completion will be strict (only items from the combo box can be selected) * if the combo box is not editable. * * @param comboBox a combo box * @param stringConverter the converter used to transform items to strings */publicstaticvoiddecorate(finalJComboBoxcomboBox,finalObjectToStringConverterstringConverter){booleanstrictMatching=!comboBox.isEditable();// has to be editablecomboBox.setEditable(true);// fix the popup locationAquaLnFPopupLocationFix.install(comboBox);// configure the text component=editor componentJTextComponenteditorComponent=(JTextComponent)comboBox.getEditor().getEditorComponent();finalAbstractAutoCompleteAdaptoradaptor=newComboBoxAdaptor(comboBox);finalAutoCompleteDocumentdocument=newAutoCompleteDocument(adaptor,strictMatching,stringConverter);decorate(editorComponent,document,adaptor);// show the popup list when the user presses a keyfinalKeyListenerkeyListener=newKeyAdapter(){@OverridepublicvoidkeyPressed(KeyEventkeyEvent){// don't popup on action keys (cursor movements, etc...)if(keyEvent.isActionKey())return;// don't popup if the combobox isn't visible anywayif(comboBox.isDisplayable()&&!comboBox.isPopupVisible()){intkeyCode=keyEvent.getKeyCode();// don't popup when the user hits shift,ctrl or altif(keyCode==KeyEvent.VK_SHIFT||keyCode==KeyEvent.VK_CONTROL||keyCode==KeyEvent.VK_ALT)return;// don't popup when the user hits escape (see issue #311)if(keyCode==KeyEvent.VK_ESCAPE||keyCode==KeyEvent.VK_ENTER)return;if(keyEvent.isAltDown()||keyEvent.isControlDown())return;comboBox.setPopupVisible(true);}}};editorComponent.addKeyListener(keyListener);if(stringConverter!=ObjectToStringConverter.DEFAULT_IMPLEMENTATION){comboBox.setEditor(newAutoCompleteComboBoxEditor(comboBox.getEditor(),stringConverter));}// Changing the l&f can change the combobox' editor which in turn// would not be autocompletion-enabled. The new editor needs to be// set-up.comboBox.addPropertyChangeListener("editor",newPropertyChangeListener(){publicvoidpropertyChange(PropertyChangeEvente){ComboBoxEditoreditor=(ComboBoxEditor)e.getNewValue();if(editor!=null&&editor.getEditorComponent()!=null){if(!(editorinstanceofAutoCompleteComboBoxEditor)&&stringConverter!=ObjectToStringConverter.DEFAULT_IMPLEMENTATION){comboBox.setEditor(newAutoCompleteComboBoxEditor(editor,stringConverter));// Don't do the decorate step here because// calling setEditor will trigger// the propertychange listener a second time,// which will do the decorate// and addKeyListener step.}else{decorate((JTextComponent)editor.getEditorComponent(),document,adaptor);editor.getEditorComponent().addKeyListener(keyListener);}}}});}/** * Decorates a given text component for automatic completion using the given * AutoCompleteDocument and AbstractAutoCompleteAdaptor. * * @param textComponent a text component that should be decorated * @param document the AutoCompleteDocument to be installed on the text * component * @param adaptor the AbstractAutoCompleteAdaptor to be used */publicstaticvoiddecorate(JTextComponenttextComponent,AutoCompleteDocumentdocument,finalAbstractAutoCompleteAdaptoradaptor){// install the document on the text componenttextComponent.setDocument(document);// mark entire text when the text component gains focus// otherwise the last mark would have been retained which is quiet// confusingtextComponent.addFocusListener(newFocusAdapter(){@OverridepublicvoidfocusGained(FocusEvente){adaptor.markEntireText();}});// Tweak some key bindingsInputMapeditorInputMap=textComponent.getInputMap();if(document.isStrictMatching()){// move the selection to the left on VK_BACK_SPACEeditorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE,0),DefaultEditorKit.selectionBackwardAction);// ignore VK_DELETE and CTRL+VK_X and beep instead when strict// matchingeditorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DELETE,0),errorFeedbackAction);editorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X,java.awt.event.InputEvent.CTRL_DOWN_MASK),errorFeedbackAction);}else{ActionMapeditorActionMap=textComponent.getActionMap();// leave VK_DELETE and CTRL+VK_X as is// VK_BACKSPACE will move the selection to the left if the selected// item is in the list// it will delete the previous character otherwiseeditorInputMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE,0),"nonstrict-backspace");editorActionMap.put("nonstrict-backspace",newNonStrictBackspaceAction(editorActionMap.get(DefaultEditorKit.deletePrevCharAction),editorActionMap.get(DefaultEditorKit.selectionBackwardAction),adaptor));}}staticclassNonStrictBackspaceActionextendsTextAction{Actionbackspace;ActionselectionBackward;AbstractAutoCompleteAdaptoradaptor;publicNonStrictBackspaceAction(Actionbackspace,ActionselectionBackward,AbstractAutoCompleteAdaptoradaptor){super("nonstrict-backspace");this.backspace=backspace;this.selectionBackward=selectionBackward;this.adaptor=adaptor;}publicvoidactionPerformed(ActionEvente){if(adaptor.listContainsSelectedItem()){selectionBackward.actionPerformed(e);}else{backspace.actionPerformed(e);}}}/** * A TextAction that provides an error feedback for the text component that * invoked the action. The error feedback is most likely a "beep". */staticObjecterrorFeedbackAction=newTextAction("provide-error-feedback"){publicvoidactionPerformed(ActionEvente){UIManager.getLookAndFeel().provideErrorFeedback(getTextComponent(e));}};}
Irmao.. onde da pra pegar os jar's usados nessa classe
cara consegui implementar sua classe, mas me responde uma pergunta ele não filtra os dados da jComboBox sendo q os dados vem do banco?
att,
ViniGodoy
Devia filtrar qualquer coisa.
habinovich
Mesmo puxando os dados do banco?
pq qnd vou digitar ele não filtra mostra todos os dados q tem na tabela sem fazer o filtro e permanece assim ate terminar de digitar…
ViniGodoy
Ele filtra o conteúdo que estiver no combo. Não interessa se você carregou do banco, ou de qualquer outro lugar.
habinovich
Eh entao acho q estou fazendo algo muito errado…
qnd vc implemento ele o combo ficava em branco e na medida que ia digitar ele ia dando as opção que tem com as letras ja digitadas n era isso?
ViniGodoy
Isso… e é isso que é auto-complete. Você quer dar opções que não estão na combo? O que você quer exatamente?
habinovich
Me parece q agora esta dando certo mas ele ta mostrando o caminho do pacote no qual ta a beans da tabela!!!
P
philipemm
Olá a todos eu estou utilizando o auto complete do swingX tambem só que é em um JTextArea, o problema é que quando eu digito uma palavra ele até completa a palavra só que depois da palavra completada o que eu digito não aparece mais
zicky23
boa tarde, desculpa ressussitar mais uma vez esse tópico mas qria saber como faço pra deixar meu jComboBox ou JTextField auto completável com essa classe???
aguardo uma ajuda…
valeu!!!
zicky23
opa, consegui implementar da seguinte forma
espero que esteja certo.
// formata a comboprivatevoiddecoraComboContrib(){grafica.ClasseAutoComplete.decorate(ComboContrib);}//preenche a comboprivatevoidComboContrib(){ObjectcodSituacao,nomeSituacoes;conn.executeSQL("SELECT s.id_situacao,s.nome_situacoes"+" FROM SITUACOES s ORDER BY id_situacao");try{ComboContrib.addItem("Selecione");while(conn.resultset.next()){codSituacao=conn.resultset.getInt("id_situacao");nomeSituacoes=conn.resultset.getString("nome_situacoes");ComboContrib.addItem(nomeSituacoes);}}catch(SQLExceptionex){Logger.getLogger(NovoServico.class.getName()).log(Level.SEVERE,null,ex);}}
até ai blz, só gostaria de saber se tem como liberar a digitação para dados q nao estejam na combo.
tipo qro cadastrar outro tipo de situacao aki neste caso. tem como?