Java Swing的多列自动完成组合框 [英] java swing multi column autocomplete combobox
问题描述
我需要高效的产品项搜索的GUI应用程序销售点,目前我使用弹出的文本字段,它包括表,但它是没有效率。
在弹出我只显示产品code我需要出示其他产品细节,例如code,类别,名称,价格等,以确定正确的产品。
![在这里输入的形象描述] [1]
以下图片是我的要求。
//////////////////////////////
我有编辑mr.splungebob回答打造AutoCompleate组合框,但与目录问题>过滤请查看code和帮助我发展了。
以下是code我已经加入到答案
// DetailedComboBox
/ *
*要改变这种模板,选择Tools |模板
*并打开编辑器的模板。
* /
封装测试; 进口java.awt.Dimension中;
进口java.awt.EventQueue中;
进口java.awt.Point中;
java.awt.event中导入*。
进口的java.util。*;
进口的javax.swing *。
进口javax.swing.event.ListSelectionEvent;
进口javax.swing.event.ListSelectionListener;
进口javax.swing.plaf.basic.BasicComboPopup中;进口javax.swing.plaf.basic.ComboPopup中;
进口javax.swing.plaf.metal.MetalComboBoxUI;
进口javax.swing.table.AbstractTableModel中;
进口javax.swing.table.TableColumn中;
进口javax.swing.table.TableColumnModel中;/ **
*
* @author W.A.R.R.Wijesinghe
* /
公共类DetailedComboBox JComboBox的扩展{ 公共静态枚举对齐{ 左右
}
私人列表<名单,LT ;?扩展对象>>资料表;
私有String [] COLUMNNAMES;
私人诠释[]列宽;
私人诠释displayColumn;
私人对准popupAlignment = Alignment.LEFT; / **
*构造一个TableComboBox对象
* /
公共DetailedComboBox(字符串[] colNames,INT [] colWidths,诠释displayColumnIndex){
超();
this.columnNames = colNames;
this.columnWidths = colWidths;
this.displayColumn = displayColumnIndex; setUI(新TableComboBoxUI());
setEditable(真);
this.setSelectedIndex(-1);
JTextField的领域=(JTextField中)this.getEditor()getEditorComponent()。
field.setText();
field.addKeyListener(新ComboKeyHandler(本));
} / **
*设置对齐类型的弹出表格
* /
公共无效setPopupAlignment(校准对齐){
popupAlignment =对齐;
} / **
*填充组合框和下拉表中提供的数据。如果
*提供的名单非空非空,假设数据是一个
*列出清单用于下拉表。组合框也
*填充从柱所限定的列数据
*< code基displayColumn< / code取代。
* /
公共无效setTableData(列表<名单,LT ;?扩展对象>>资料表){
this.tableData =(资料表== NULL
?新的ArrayList<名单,LT ;?扩展对象>>():资料表); //即使输入数据为所述表中,我们还必须
//填充组合框的数据,因此首先清除previous列表。
removeAllItems(); //然后从合适的列数据装入组合框
迭代器<名单,LT ;?扩展对象>> ITER = this.tableData.iterator();
而(iter.hasNext()){
名单,LT ;?扩展对象> rowData = iter.next();
的addItem(rowData.get(displayColumn));
}
} 公开名单&LT ;?扩展对象> getSelectedRow(){
返回tableData.get(getSelectedIndex());
} 公开名单&LT ;?扩展对象> getRowAt(INT行){
返回tableData.get(行);
} / **
*为组合框的组件处理程序
* /
私有类TableComboBoxUI扩展MetalComboBoxUI { / **
*创建的组合框的弹出组件
* /
@覆盖
保护ComboPopup createPopup(){
返回新TableComboPopup(组合框,这一点);
} / **
*返回JList组件
* /
公共JList中的GetList(){
返回列表框;
}
} / **
*组合框,这是一个JTable,而不是一个JList,的下拉。
* /
私有类TableComboPopup扩展BasicComboPopup实现ListSelectionListener,{的ItemListener 私人最终JTable的表;
私人TableComboBoxUI comboBoxUI;
私人PopupTableModel TableModel的;
私人JScrollPane的滚动;
//私人JList的列表=新的JList();
//私人ListSelectionListener SelectionListener中;
//私人的ItemListener的ItemListener; / **
*构造一个弹出组件,这是一个表
* /
公共TableComboPopup(JComboBox的组合,TableComboBoxUI UI){
超(组合);
this.comboBoxUI = UI; TableModel的=新PopupTableModel();
表=新的JTable(TableModel的);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
。table.getTableHeader()setReorderingAllowed(假); TableColumnModel的TableColumnModel的= table.getColumnModel();
tableColumnModel.setColumnSelectionAllowed(假); 对于(INT指数= 0;指数 - LT; table.getColumnCount();指数++){
TableColumn的TableColumn的= tableColumnModel.getColumn(指数);
tableColumn.set preferredWidth(列宽[指数]);
} 滚动=新JScrollPane的(表);
scroll.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); selectionModel的的ListSelectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
selectionModel.addListSelectionListener(本);
combo.addItemListener(本); table.addMouseListener(新MouseAdapter(){ @覆盖
公共无效鼠标pressed(事件的MouseEvent){
点P = event.getPoint();
INT行= table.rowAtPoint(P); comboBox.setSelectedIndex(行);
隐藏();
}
}); table.setBackground(UIManager.getColor(ComboBox.listBackground));
table.setForeground(UIManager.getColor(ComboBox.listForeground));
} / **
*这个方法是从BasicComboPopup覆盖
* /
@覆盖
公共无效显示(){
如果(isEnabled()){
super.removeAll(); INT scrollWidth = table.get preferredSize()。width方法
+((整数)UIManager.get将按(ScrollBar.width))的intValue()+1。
INT scrollHeight属性= comboBoxUI.getList()。
GET preferredScrollableViewportSize()的高度。
scroll.set preferredSize(新尺寸(scrollWidth,scrollHeight属性)); super.add(滚动); selectionModel的的ListSelectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(本);
selectRow();
selectionModel.addListSelectionListener(本); INT scrollX = 0;
INT scrollY = comboBox.getBounds()的高度。 如果(popupAlignment == Alignment.RIGHT){
scrollX = comboBox.getBounds()宽度 - scrollWidth。
} 秀(组合框,scrollX,scrollY);
}
} / **
* ListSelectionListener的FPGA实现
* /
@覆盖
公共无效的valueChanged(ListSelectionEvent事件){
comboBox.setSelectedIndex(table.getSelectedRow());
} / **
*的ItemListener的FPGA实现
* /
@覆盖
公共无效itemStateChanged(一个ItemEvent事件){
如果(event.getStateChange()!= ItemEvent.DESELECTED){
selectionModel的的ListSelectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(本);
selectRow();
selectionModel.addListSelectionListener(本);
}
} / **
*同步表中的选定行与的选定行
*组合。
* /
私人无效selectRow(){
INT指数= comboBox.getSelectedIndex(); 如果(指数!= -1){
table.setRowSelectionInterval(索引,索引);
table.scrollRectToVisible(table.getCellRect(指数为0,真正的));
}
}
} / **
*一个用于弹出表的数据模型
* /
私有类PopupTableModel扩展AbstractTableModel上{ / **
*返回列#在下拉表
* /
@覆盖
公众诠释getColumnCount(){
返回columnNames.length;
} / **
*返回的行#在下拉表
* /
@覆盖
公众诠释getRowCount(){
返回资料表== NULL? 0:tableData.size();
} / **
*确定的值对于给定小区
* /
@覆盖
公共对象getValueAt(INT行,诠释山口){
如果(资料表== NULL || tableData.size()== 0){
返回;
} 返回tableData.get(行)获得(COL);
} / **
*在下拉表中的所有细胞是不可编辑
* /
@覆盖
公共布尔的isCellEditable(INT行,诠释山口){
返回false;
} / **
*拉列名了tableInfo对象的头
* /
@覆盖
公共字符串getColumnName(INT列){
字符串COLUMNNAME = NULL; 如果(列> = 0&放大器;&安培;柱< columnNames.length){
COLUMNNAME = COLUMNNAMES [专栏]的ToString();
} 返回(COLUMNNAME == NULL)? super.getColumnName(列):COLUMNNAME;
}
}
}类ComboKeyHandler扩展KeyAdapter { 私人最终DetailedComboBox组合框;
//私人最终矢量<串GT;名单=新的矢量<串GT;();
私人最终名单<名单,LT;>>名单=新的ArrayList<>(); 公共ComboKeyHandler(DetailedComboBox组合){
this.comboBox =组合;
的for(int i = 0; I< comboBox.getModel()的getSize();我++){
名单,LT ;?扩展对象> rowData = combo.getRowAt(ⅰ);
// name.setText(rowData.get(1)的ToString());
// capital.setText(rowData.get(2)的ToString());
list.add(rowData);
// list.addElement((字符串)comboBox.getItemAt(一));
}
}
私人布尔shouldHide = FALSE; @覆盖
公共无效的keyTyped(最终KeyEvent的E){
EventQueue.invokeLater(新的Runnable(){ @覆盖
公共无效的run(){
字符串文本=((JTextField中)e.getSource())的getText()。
的System.out.println(文本);
如果(text.length()== 0){
setSuggestionModel(组合框,列表,);
comboBox.hidePopup();
}其他{
清单<名单,LT;>> M = getSuggestedModel(列表,文本);
如果(m.isEmpty()|| shouldHide){
comboBox.hidePopup();
}其他{
setSuggestionModel(组合框,男,文字);
comboBox.showPopup();
}
}
}
});
} @覆盖
公共无效键pressed(KeyEvent的E){
JTextField的文本框=(JTextField中)e.getSource();
字符串文本= textField.getText();
shouldHide = FALSE;
开关(e.getKey code()){
案例KeyEvent.VK_RIGHT:
对于(迭代器<名单,LT;>>其= list.iterator(); it.hasNext();){
如果(!it.next()。包含(如何)){
it.remove(); //注意:迭代器的remove方法,而不是ArrayList中的,被使用。
}
返回;
} / *
*对于(一个String:清单{如果(s.startsWith(文本)){
* textField.setText(多个);返回; }}
*
* / 打破;
案例KeyEvent.VK_ENTER:
如果(!list.contains(文本)){
list.add(新的ArrayList&所述;>(Arrays.asList(文字一,一个))); // setSuggestionModel(组合框,新的DefaultComboBoxModel(列表),文本);
setSuggestionModel(组合框,getSuggestedModel(列表,文本),文本);
}
shouldHide = FALSE;
打破;
案例KeyEvent.VK_ESCAPE:
shouldHide = TRUE;
打破;
默认:
打破;
}
} 私有静态无效setSuggestionModel(DetailedComboBox组合框,列表<名单,LT;>> newList,字符串str){
comboBox.setTableData(newList);
comboBox.setSelectedIndex(-1);
(。(JTextField中)comboBox.getEditor()getEditorComponent())的setText(STR)。
} 私人静态列表<名单,LT;>> getSuggestedModel(列表<名单,LT;>>列表中,字符串文本){
清单<名单,LT;>> M =新的ArrayList<>();
对于(迭代器<名单,LT;>>其= list.iterator(); it.hasNext();){
如果(!it.next()。包含(文本)){
it.remove(); //注意:迭代器的remove方法,而不是ArrayList中的,被使用。
}
M =(列表<名单,LT;>>)它;
}
返回米; / *
*对于(一个String:名单){如果(s.startsWith(文本)){m.addElement(S); }
*}回报米;
*
* /
}
}
// DetailedComboBoxDemo
/ *
*要改变这种模板,选择Tools |模板
*并打开编辑器的模板。
* /
封装测试;进口java.awt.BorderLayout中;
进口java.awt.FlowLayout中;
进口java.awt.event.ActionEvent中;
进口java.awt.event.ActionListener;
进口的java.util.ArrayList;
进口java.util.Arrays中;
进口的java.util.List;
进口的javax.swing *。/ **
*
* @author W.A.R.R.Wijesinghe
* /
公共类DetailedComboBoxDemo实现Runnable { 私人DetailedComboBox组合;
私人JTextField的名称;
私人资本的JTextField; @覆盖
公共无效的run(){
清单<名单,LT;>>资料表=新的ArrayList<>();
tableData.add(新的ArrayList&所述;>(Arrays.asList(MD,马里兰,安纳波利斯))); tableData.add(新的ArrayList<>(
Arrays.asList(NH,新罕布什尔,协和)));
tableData.add(新的ArrayList<>(
Arrays.asList(新泽西州,新泽西,特伦顿)));
tableData.add(新的ArrayList<>(
Arrays.asList(NM,新墨西哥,圣达菲)));
tableData.add(新的ArrayList<>(
Arrays.asList(ND,北达科他州,俾斯麦))); 的String [] =列新的String [] {国家,姓名,资本论};
INT [] =宽度INT新[] {50,100,100}; 二合一=新DetailedComboBox(列,宽度,0);
combo.setTableData(资料表);
combo.setSelectedIndex(-1);
combo.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
combo.addActionListener(新的ActionListener(){ @覆盖
公共无效的actionPerformed(ActionEvent的五){
显示详细资料();
}
}); 名称=新的JTextField(10);
资本=新的JTextField(10);
name.setEditable(假);
capital.setEditable(假); JPanel的P =新JPanel(新的FlowLayout());
p.add(新的JLabel(国家));
p.add(组合);
p.add(新的JLabel(姓名));
p.add(名);
p.add(新的JLabel(资本));
p.add(资本); JFrame的帧=新的JFrame(DetailedComboBox演示); 。frame.getContentPane()增加(P,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(NULL);
frame.setVisible(真);
} 私人无效showDetails(){
名单,LT ;?扩展对象> rowData = combo.getSelectedRow();
name.setText(rowData.get(1)的ToString());
capital.setText(rowData.get(2)的ToString());
} 公共静态无效的主要(字串[] args){
SwingUtilities.invokeLater(新DetailedComboBoxDemo());
}
}
下面是一个使用一个JTable为它的下拉列表,而不是一个JList,的JComboBox。你需要给它表数据(列表的列表),而不是通常的。对不起,没有自动完成。
我已经使用了多年。它的工作原理,但我不作任何承诺。哎呀,甚至有可能是从实验有吃剩的一些死code。这只是一个来自不同的想法,我从不同code样本多年来抢下米什MOSH。我敢肯定有改进的空间。
DetailedComboBox:
进口java.awt中的*。
java.awt.event中导入*。
进口的java.util。*;
进口的java.util.List;进口的javax.swing *。
javax.swing.event中导入*。
javax.swing.plaf.basic中导入*。
导入的javax.swing.plaf.metal *。
导入的javax.swing.table *。/ **
*一个JComboBox,有一个JTable作为下拉,而不是一个JList,
* /
公共类DetailedComboBox JComboBox的扩展
{
公共静态枚举对齐{左,右} 私人列表<名单,LT ;?扩展对象>>资料表;
私有String [] COLUMNNAMES;
私人诠释[]列宽;
私人诠释displayColumn;
私人对准popupAlignment = Alignment.LEFT; / **
*构造一个TableComboBox对象
* /
公共DetailedComboBox(字符串[] colNames,INT [] colWidths,
INT displayColumnIndex)
{
超();
this.columnNames = colNames;
this.columnWidths = colWidths;
this.displayColumn = displayColumnIndex; setUI(新TableComboBoxUI());
setEditable(假);
} / **
*设置对齐类型的弹出表格
* /
公共无效setPopupAlignment(校准对齐)
{
popupAlignment =对齐;
} / **
*填充组合框和下拉表中提供的数据。
*如果提供的列表非空非空,假设
*数据是要用于下拉表列表的列表。
*组合框还填充了列数据
*以&lt定义的列; displayColumn其中p code&GT / code取代。
* /
公共无效setTableData(列表<名单,LT ;?扩展对象>>资料表)
{
this.tableData =(资料表== NULL?
新的ArrayList<名单,LT ;?扩展对象>>():资料表); //即使输入数据为所述表中,我们还必须
//填充组合框的数据,因此首先清除previous列表。
removeAllItems(); //然后从合适的列数据装入组合框
迭代器<名单,LT ;?扩展对象>> ITER = this.tableData.iterator();
而(iter.hasNext())
{
名单,LT ;?扩展对象> rowData = iter.next();
的addItem(rowData.get(displayColumn));
}
} 公开名单&LT ;?扩展对象> getSelectedRow()
{
返回tableData.get(getSelectedIndex());
} / **
*为组合框的组件处理程序
* /
私有类TableComboBoxUI扩展MetalComboBoxUI
{
/ **
*创建的组合框的弹出组件
* /
@覆盖
保护ComboPopup createPopup()
{
返回新TableComboPopup(组合框,这一点);
} / **
*返回JList组件
* /
公共JList中的GetList()
{
返回列表框;
}
} / **
*组合框,这是一个JTable,而不是一个JList,的下拉。
* /
私有类TableComboPopup扩展BasicComboPopup
实现ListSelectionListener,的ItemListener
{
私人最终JTable的表; 私人TableComboBoxUI comboBoxUI;
私人PopupTableModel TableModel的;
私人JScrollPane的滚动;
//私人JList的列表=新的JList();
//私人ListSelectionListener SelectionListener中;
//私人的ItemListener的ItemListener; / **
*构造一个弹出组件,这是一个表
* /
公共TableComboPopup(JComboBox的组合,TableComboBoxUI UI)
{
超(组合);
this.comboBoxUI = UI; TableModel的=新PopupTableModel();
表=新的JTable(TableModel的);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
。table.getTableHeader()setReorderingAllowed(假); TableColumnModel的TableColumnModel的= table.getColumnModel();
tableColumnModel.setColumnSelectionAllowed(假); 对于(INT指数= 0;指数 - LT; table.getColumnCount();指数++)
{
TableColumn的TableColumn的= tableColumnModel.getColumn(指数);
tableColumn.set preferredWidth(列宽[指数]);
} 滚动=新JScrollPane的(表);
scroll.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); selectionModel的的ListSelectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
selectionModel.addListSelectionListener(本);
combo.addItemListener(本); table.addMouseListener(新MouseAdapter()
{
@覆盖
公共无效鼠标pressed(事件的MouseEvent)
{
点P = event.getPoint();
INT行= table.rowAtPoint(P); comboBox.setSelectedIndex(行);
隐藏();
}
}); table.setBackground(UIManager.getColor(ComboBox.listBackground));
table.setForeground(UIManager.getColor(ComboBox.listForeground));
} / **
*这个方法是从BasicComboPopup覆盖
* /
@覆盖
公共无效显示()
{
如果(isEnabled())
{
super.removeAll(); INT scrollWidth = table.get preferredSize()。宽+
((整数)UIManager.get将按(ScrollBar.width))的intValue()+ 1;
INT scrollHeight属性= comboBoxUI.getList()。
GET preferredScrollableViewportSize()的高度。
scroll.set preferredSize(新尺寸(scrollWidth,scrollHeight属性)); super.add(滚动); selectionModel的的ListSelectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(本);
selectRow();
selectionModel.addListSelectionListener(本); INT scrollX = 0;
INT scrollY = comboBox.getBounds()的高度。 如果(popupAlignment == Alignment.RIGHT)
{
scrollX = comboBox.getBounds()宽度 - scrollWidth。
} 秀(组合框,scrollX,scrollY);
}
} / **
* ListSelectionListener的FPGA实现
* /
公共无效的valueChanged(ListSelectionEvent事件)
{
comboBox.setSelectedIndex(table.getSelectedRow());
} / **
*的ItemListener的FPGA实现
* /
公共无效itemStateChanged(一个ItemEvent事件)
{
如果(event.getStateChange()!= ItemEvent.DESELECTED)
{
selectionModel的的ListSelectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(本);
selectRow();
selectionModel.addListSelectionListener(本);
}
} / **
*同步表中的所选择的行与组合的选定行。
* /
私人无效selectRow()
{
INT指数= comboBox.getSelectedIndex(); 如果(索引!= -1)
{
table.setRowSelectionInterval(索引,索引);
table.scrollRectToVisible(table.getCellRect(指数为0,真正的));
}
}
} / **
*一个用于弹出表的数据模型
* /
私有类PopupTableModel扩展AbstractTableModel上
{
/ **
*返回列#在下拉表
* /
公众诠释getColumnCount()
{
返回columnNames.length;
} / **
*返回的行#在下拉表
* /
公众诠释getRowCount()
{
返回资料表== NULL? 0:tableData.size();
} / **
*确定的值对于给定小区
* /
公共对象getValueAt(INT行,诠释山口)
{
如果(资料表== NULL || tableData.size()== 0)
{
返回;
} 返回tableData.get(行)获得(COL);
} / **
*在下拉表中的所有细胞是不可编辑
* /
@覆盖
公共布尔的isCellEditable(INT行,诠释山口)
{
返回false;
} / **
*拉列名了tableInfo对象的头
* /
@覆盖
公共字符串getColumnName(INT列)
{
字符串COLUMNNAME = NULL; 如果(列> = 0&放大器;&安培;柱< columnNames.length)
{
COLUMNNAME = COLUMNNAMES [专栏]的ToString();
} 返回(COLUMNNAME == NULL)? super.getColumnName(列):COLUMNNAME;
}
}
}
驱动:
进口java.awt中的*。
java.awt.event中导入*。
进口的java.util。*;
进口的java.util.List;进口的javax.swing *。公共类DetailedComboBoxDemo实现Runnable
{
私人DetailedComboBox组合;
私人JTextField的名称;
私人资本的JTextField; 公共无效的run()
{
清单<名单,LT;>>资料表=新的ArrayList<名单,LT;>>();
tableData.add(新的ArrayList<串GT;(
Arrays.asList(MD,马里兰,安纳波利斯)));
tableData.add(新的ArrayList<串GT;(
Arrays.asList(NH,新罕布什尔,协和)));
tableData.add(新的ArrayList<串GT;(
Arrays.asList(新泽西州,新泽西,特伦顿)));
tableData.add(新的ArrayList<串GT;(
Arrays.asList(NM,新墨西哥,圣达菲)));
tableData.add(新的ArrayList<串GT;(
Arrays.asList(ND,北达科他州,俾斯麦))); 的String [] =列新的String [] {国家,姓名,资本论};
INT [] =宽度INT新[] {50,100,100}; 二合一=新DetailedComboBox(列,宽度,0);
combo.setTableData(资料表);
combo.setSelectedIndex(-1);
combo.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
combo.addActionListener(新的ActionListener()
{
公共无效的actionPerformed(ActionEvent的五)
{
显示详细资料();
}
}); 名称=新的JTextField(10);
资本=新的JTextField(10);
name.setEditable(假);
capital.setEditable(假); JPanel的P =新JPanel(新的FlowLayout());
p.add(新的JLabel(国家));
p.add(组合);
p.add(新的JLabel(姓名));
p.add(名);
p.add(新的JLabel(资本));
p.add(资本); JFrame的帧=新的JFrame(DetailedComboBox演示);
。frame.getContentPane()增加(P,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(NULL);
frame.setVisible(真);
} 私人无效showDetails()
{
名单,LT ;?扩展对象> rowData = combo.getSelectedRow();
name.setText(rowData.get(1)的ToString());
capital.setText(rowData.get(2)的ToString());
} 公共静态无效的主要(字串[] args)
{
SwingUtilities.invokeLater(新DetailedComboBoxDemo());
}
}
I need efficient product item search GUI to Point of sale application, currently I am using pop up in text field and it include to table but it is not efficient.
In my popup only show product code I need to show other product detail such as CODE , category, Name ,price etc.. to determine correct product. ![enter image description here][1]
Following images are the my requirement.
////////////////////////////// I have Edit mr.splungebob answer to build AutoCompleate combobox , But It has problem with List> filtering please review code and help me to develop it.
Following are the code I have added to answer //DetailedComboBox
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
*
* @author W.A.R.R.Wijesinghe
*/
public class DetailedComboBox extends JComboBox {
public static enum Alignment {
LEFT, RIGHT
}
private List<List<? extends Object>> tableData;
private String[] columnNames;
private int[] columnWidths;
private int displayColumn;
private Alignment popupAlignment = Alignment.LEFT;
/**
* Construct a TableComboBox object
*/
public DetailedComboBox(String[] colNames, int[] colWidths, int displayColumnIndex) {
super();
this.columnNames = colNames;
this.columnWidths = colWidths;
this.displayColumn = displayColumnIndex;
setUI(new TableComboBoxUI());
setEditable(true);
this.setSelectedIndex(-1);
JTextField field = (JTextField) this.getEditor().getEditorComponent();
field.setText("");
field.addKeyListener(new ComboKeyHandler(this));
}
/**
* Set the type of alignment for the popup table
*/
public void setPopupAlignment(Alignment alignment) {
popupAlignment = alignment;
}
/**
* Populate the combobox and drop-down table with the supplied data. If the
* supplied List is non-null and non-empty, it is assumed that the data is a
* List of Lists to be used for the drop-down table. The combobox is also
* populated with the column data from the column defined by
* <code>displayColumn</code>.
*/
public void setTableData(List<List<? extends Object>> tableData) {
this.tableData = (tableData == null
? new ArrayList<List<? extends Object>>() : tableData);
// even though the incoming data is for the table, we must also
// populate the combobox's data, so first clear the previous list.
removeAllItems();
// then load the combobox with data from the appropriate column
Iterator<List<? extends Object>> iter = this.tableData.iterator();
while (iter.hasNext()) {
List<? extends Object> rowData = iter.next();
addItem(rowData.get(displayColumn));
}
}
public List<? extends Object> getSelectedRow() {
return tableData.get(getSelectedIndex());
}
public List<? extends Object> getRowAt(int row) {
return tableData.get(row);
}
/**
* The handler for the combobox's components
*/
private class TableComboBoxUI extends MetalComboBoxUI {
/**
* Create a popup component for the ComboBox
*/
@Override
protected ComboPopup createPopup() {
return new TableComboPopup(comboBox, this);
}
/**
* Return the JList component
*/
public JList getList() {
return listBox;
}
}
/**
* The drop-down of the combobox, which is a JTable instead of a JList.
*/
private class TableComboPopup extends BasicComboPopup implements ListSelectionListener, ItemListener {
private final JTable table;
private TableComboBoxUI comboBoxUI;
private PopupTableModel tableModel;
private JScrollPane scroll;
// private JList list = new JList();
// private ListSelectionListener selectionListener;
// private ItemListener itemListener;
/**
* Construct a popup component that's a table
*/
public TableComboPopup(JComboBox combo, TableComboBoxUI ui) {
super(combo);
this.comboBoxUI = ui;
tableModel = new PopupTableModel();
table = new JTable(tableModel);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
TableColumnModel tableColumnModel = table.getColumnModel();
tableColumnModel.setColumnSelectionAllowed(false);
for (int index = 0; index < table.getColumnCount(); index++) {
TableColumn tableColumn = tableColumnModel.getColumn(index);
tableColumn.setPreferredWidth(columnWidths[index]);
}
scroll = new JScrollPane(table);
scroll.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
selectionModel.addListSelectionListener(this);
combo.addItemListener(this);
table.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent event) {
Point p = event.getPoint();
int row = table.rowAtPoint(p);
comboBox.setSelectedIndex(row);
hide();
}
});
table.setBackground(UIManager.getColor("ComboBox.listBackground"));
table.setForeground(UIManager.getColor("ComboBox.listForeground"));
}
/**
* This method is overridden from BasicComboPopup
*/
@Override
public void show() {
if (isEnabled()) {
super.removeAll();
int scrollWidth = table.getPreferredSize().width
+ ((Integer) UIManager.get("ScrollBar.width")).intValue() + 1;
int scrollHeight = comboBoxUI.getList().
getPreferredScrollableViewportSize().height;
scroll.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
super.add(scroll);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(this);
selectRow();
selectionModel.addListSelectionListener(this);
int scrollX = 0;
int scrollY = comboBox.getBounds().height;
if (popupAlignment == Alignment.RIGHT) {
scrollX = comboBox.getBounds().width - scrollWidth;
}
show(comboBox, scrollX, scrollY);
}
}
/**
* Implemention of ListSelectionListener
*/
@Override
public void valueChanged(ListSelectionEvent event) {
comboBox.setSelectedIndex(table.getSelectedRow());
}
/**
* Implemention of ItemListener
*/
@Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() != ItemEvent.DESELECTED) {
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(this);
selectRow();
selectionModel.addListSelectionListener(this);
}
}
/**
* Sync the selected row of the table with the selected row of the
* combo.
*/
private void selectRow() {
int index = comboBox.getSelectedIndex();
if (index != -1) {
table.setRowSelectionInterval(index, index);
table.scrollRectToVisible(table.getCellRect(index, 0, true));
}
}
}
/**
* A model for the popup table's data
*/
private class PopupTableModel extends AbstractTableModel {
/**
* Return the # of columns in the drop-down table
*/
@Override
public int getColumnCount() {
return columnNames.length;
}
/**
* Return the # of rows in the drop-down table
*/
@Override
public int getRowCount() {
return tableData == null ? 0 : tableData.size();
}
/**
* Determine the value for a given cell
*/
@Override
public Object getValueAt(int row, int col) {
if (tableData == null || tableData.size() == 0) {
return "";
}
return tableData.get(row).get(col);
}
/**
* All cells in the drop-down table are uneditable
*/
@Override
public boolean isCellEditable(int row, int col) {
return false;
}
/**
* Pull the column names out of the tableInfo object for the header
*/
@Override
public String getColumnName(int column) {
String columnName = null;
if (column >= 0 && column < columnNames.length) {
columnName = columnNames[column].toString();
}
return (columnName == null) ? super.getColumnName(column) : columnName;
}
}
}
class ComboKeyHandler extends KeyAdapter {
private final DetailedComboBox comboBox;
// private final Vector<String> list = new Vector<String>();
private final List<List<?>> list = new ArrayList<>();
public ComboKeyHandler(DetailedComboBox combo) {
this.comboBox = combo;
for (int i = 0; i < comboBox.getModel().getSize(); i++) {
List<? extends Object> rowData = combo.getRowAt(i);
// name.setText(rowData.get(1).toString());
// capital.setText(rowData.get(2).toString());
list.add(rowData);
// list.addElement((String) comboBox.getItemAt(i));
}
}
private boolean shouldHide = false;
@Override
public void keyTyped(final KeyEvent e) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
String text = ((JTextField) e.getSource()).getText();
System.out.println(text);
if (text.length() == 0) {
setSuggestionModel(comboBox, list, "");
comboBox.hidePopup();
} else {
List<List<?>> m = getSuggestedModel(list, text);
if (m.isEmpty() || shouldHide) {
comboBox.hidePopup();
} else {
setSuggestionModel(comboBox, m, text);
comboBox.showPopup();
}
}
}
});
}
@Override
public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getSource();
String text = textField.getText();
shouldHide = false;
switch (e.getKeyCode()) {
case KeyEvent.VK_RIGHT:
for (Iterator<List<?>> it = list.iterator(); it.hasNext();) {
if (!it.next().contains("How")) {
it.remove(); // NOTE: Iterator's remove method, not ArrayList's, is used.
}
return;
}
/*
* for (String s : list { if (s.startsWith(text)) {
* textField.setText(s); return; } }
*
*/
break;
case KeyEvent.VK_ENTER:
if (!list.contains(text)) {
list.add(new ArrayList<>(Arrays.asList(text, "a", "a")));
//setSuggestionModel(comboBox, new DefaultComboBoxModel(list), text);
setSuggestionModel(comboBox, getSuggestedModel(list, text), text);
}
shouldHide = false;
break;
case KeyEvent.VK_ESCAPE:
shouldHide = true;
break;
default:
break;
}
}
private static void setSuggestionModel(DetailedComboBox comboBox, List<List<?>> newList, String str) {
comboBox.setTableData(newList);
comboBox.setSelectedIndex(-1);
((JTextField) comboBox.getEditor().getEditorComponent()).setText(str);
}
private static List<List<?>> getSuggestedModel(List<List<?>> list, String text) {
List<List<?>> m = new ArrayList<>();
for (Iterator<List<?>> it = list.iterator(); it.hasNext();) {
if (!it.next().contains(text)) {
it.remove(); // NOTE: Iterator's remove method, not ArrayList's, is used.
}
m = (List<List<?>>) it;
}
return m;
/*
* for (String s : list) { if (s.startsWith(text)) { m.addElement(s); }
* } return m;
*
*/
}
}
//DetailedComboBoxDemo
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;
/**
*
* @author W.A.R.R.Wijesinghe
*/
public class DetailedComboBoxDemo implements Runnable {
private DetailedComboBox combo;
private JTextField name;
private JTextField capital;
@Override
public void run() {
List<List<?>> tableData = new ArrayList<>();
tableData.add(new ArrayList<>( Arrays.asList("MD", "Maryland", "Annapolis")));
tableData.add(new ArrayList<>(
Arrays.asList("NH", "New Hampshire", "Concord")));
tableData.add(new ArrayList<>(
Arrays.asList("NJ", "New Jersey", "Trenton")));
tableData.add(new ArrayList<>(
Arrays.asList("NM", "New Mexico", "Santa Fe")));
tableData.add(new ArrayList<>(
Arrays.asList("ND", "North Dakota", "Bismark")));
String[] columns = new String[]{"State", "Name", "Capital"};
int[] widths = new int[]{50, 100, 100};
combo = new DetailedComboBox(columns, widths, 0);
combo.setTableData(tableData);
combo.setSelectedIndex(-1);
combo.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
combo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
showDetails();
}
});
name = new JTextField(10);
capital = new JTextField(10);
name.setEditable(false);
capital.setEditable(false);
JPanel p = new JPanel(new FlowLayout());
p.add(new JLabel("State"));
p.add(combo);
p.add(new JLabel("Name"));
p.add(name);
p.add(new JLabel("Capital"));
p.add(capital);
JFrame frame = new JFrame("DetailedComboBox Demo");
frame.getContentPane().add(p, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void showDetails() {
List<? extends Object> rowData = combo.getSelectedRow();
name.setText(rowData.get(1).toString());
capital.setText(rowData.get(2).toString());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new DetailedComboBoxDemo());
}
}
Here's a JComboBox that uses a JTable for it's drop-down instead of a JList. You need to give it table data (a List of Lists) instead of the usual. Sorry, there's no auto-complete.
I've been using this for years. It works, but I make no promises. Heck, there may even be some dead code in there leftover from experimentation. It's just a mish-mosh from different ideas I grabbed from different code samples over the years. I'm sure there's room for improvement.
DetailedComboBox:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;
import javax.swing.table.*;
/**
* A JComboBox that has a JTable as a drop-down instead of a JList
*/
public class DetailedComboBox extends JComboBox
{
public static enum Alignment {LEFT, RIGHT}
private List<List<? extends Object>> tableData;
private String[] columnNames;
private int[] columnWidths;
private int displayColumn;
private Alignment popupAlignment = Alignment.LEFT;
/**
* Construct a TableComboBox object
*/
public DetailedComboBox(String[] colNames, int[] colWidths,
int displayColumnIndex)
{
super();
this.columnNames = colNames;
this.columnWidths = colWidths;
this.displayColumn = displayColumnIndex;
setUI(new TableComboBoxUI());
setEditable(false);
}
/**
* Set the type of alignment for the popup table
*/
public void setPopupAlignment(Alignment alignment)
{
popupAlignment = alignment;
}
/**
* Populate the combobox and drop-down table with the supplied data.
* If the supplied List is non-null and non-empty, it is assumed that
* the data is a List of Lists to be used for the drop-down table.
* The combobox is also populated with the column data from the
* column defined by <code>displayColumn</code>.
*/
public void setTableData(List<List<? extends Object>> tableData)
{
this.tableData = (tableData == null ?
new ArrayList<List<? extends Object>>() : tableData);
// even though the incoming data is for the table, we must also
// populate the combobox's data, so first clear the previous list.
removeAllItems();
// then load the combobox with data from the appropriate column
Iterator<List<? extends Object>> iter = this.tableData.iterator();
while (iter.hasNext())
{
List<? extends Object> rowData = iter.next();
addItem(rowData.get(displayColumn));
}
}
public List<? extends Object> getSelectedRow()
{
return tableData.get(getSelectedIndex());
}
/**
* The handler for the combobox's components
*/
private class TableComboBoxUI extends MetalComboBoxUI
{
/**
* Create a popup component for the ComboBox
*/
@Override
protected ComboPopup createPopup()
{
return new TableComboPopup(comboBox, this);
}
/**
* Return the JList component
*/
public JList getList()
{
return listBox;
}
}
/**
* The drop-down of the combobox, which is a JTable instead of a JList.
*/
private class TableComboPopup extends BasicComboPopup
implements ListSelectionListener, ItemListener
{
private final JTable table;
private TableComboBoxUI comboBoxUI;
private PopupTableModel tableModel;
private JScrollPane scroll;
// private JList list = new JList();
// private ListSelectionListener selectionListener;
// private ItemListener itemListener;
/**
* Construct a popup component that's a table
*/
public TableComboPopup(JComboBox combo, TableComboBoxUI ui)
{
super(combo);
this.comboBoxUI = ui;
tableModel = new PopupTableModel();
table = new JTable(tableModel);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
TableColumnModel tableColumnModel = table.getColumnModel();
tableColumnModel.setColumnSelectionAllowed(false);
for (int index = 0; index < table.getColumnCount(); index++)
{
TableColumn tableColumn = tableColumnModel.getColumn(index);
tableColumn.setPreferredWidth(columnWidths[index]);
}
scroll = new JScrollPane(table);
scroll.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
selectionModel.addListSelectionListener(this);
combo.addItemListener(this);
table.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent event)
{
Point p = event.getPoint();
int row = table.rowAtPoint(p);
comboBox.setSelectedIndex(row);
hide();
}
});
table.setBackground(UIManager.getColor("ComboBox.listBackground"));
table.setForeground(UIManager.getColor("ComboBox.listForeground"));
}
/**
* This method is overridden from BasicComboPopup
*/
@Override
public void show()
{
if (isEnabled())
{
super.removeAll();
int scrollWidth = table.getPreferredSize().width +
((Integer) UIManager.get("ScrollBar.width")).intValue() + 1;
int scrollHeight = comboBoxUI.getList().
getPreferredScrollableViewportSize().height;
scroll.setPreferredSize(new Dimension(scrollWidth, scrollHeight));
super.add(scroll);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(this);
selectRow();
selectionModel.addListSelectionListener(this);
int scrollX = 0;
int scrollY = comboBox.getBounds().height;
if (popupAlignment == Alignment.RIGHT)
{
scrollX = comboBox.getBounds().width - scrollWidth;
}
show(comboBox, scrollX, scrollY);
}
}
/**
* Implemention of ListSelectionListener
*/
public void valueChanged(ListSelectionEvent event)
{
comboBox.setSelectedIndex(table.getSelectedRow());
}
/**
* Implemention of ItemListener
*/
public void itemStateChanged(ItemEvent event)
{
if (event.getStateChange() != ItemEvent.DESELECTED)
{
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.removeListSelectionListener(this);
selectRow();
selectionModel.addListSelectionListener(this);
}
}
/**
* Sync the selected row of the table with the selected row of the combo.
*/
private void selectRow()
{
int index = comboBox.getSelectedIndex();
if (index != -1)
{
table.setRowSelectionInterval(index, index);
table.scrollRectToVisible(table.getCellRect(index, 0, true));
}
}
}
/**
* A model for the popup table's data
*/
private class PopupTableModel extends AbstractTableModel
{
/**
* Return the # of columns in the drop-down table
*/
public int getColumnCount()
{
return columnNames.length;
}
/**
* Return the # of rows in the drop-down table
*/
public int getRowCount()
{
return tableData == null ? 0 : tableData.size();
}
/**
* Determine the value for a given cell
*/
public Object getValueAt(int row, int col)
{
if (tableData == null || tableData.size() == 0)
{
return "";
}
return tableData.get(row).get(col);
}
/**
* All cells in the drop-down table are uneditable
*/
@Override
public boolean isCellEditable(int row, int col)
{
return false;
}
/**
* Pull the column names out of the tableInfo object for the header
*/
@Override
public String getColumnName(int column)
{
String columnName = null;
if (column >= 0 && column < columnNames.length)
{
columnName = columnNames[column].toString();
}
return (columnName == null) ? super.getColumnName(column) : columnName;
}
}
}
Driver:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class DetailedComboBoxDemo implements Runnable
{
private DetailedComboBox combo;
private JTextField name;
private JTextField capital;
public void run()
{
List<List<?>> tableData = new ArrayList<List<?>>();
tableData.add(new ArrayList<String>(
Arrays.asList("MD", "Maryland", "Annapolis")));
tableData.add(new ArrayList<String>(
Arrays.asList("NH", "New Hampshire", "Concord")));
tableData.add(new ArrayList<String>(
Arrays.asList("NJ", "New Jersey", "Trenton")));
tableData.add(new ArrayList<String>(
Arrays.asList("NM", "New Mexico", "Santa Fe")));
tableData.add(new ArrayList<String>(
Arrays.asList("ND", "North Dakota", "Bismark")));
String[] columns = new String[]{"State", "Name", "Capital"};
int[] widths = new int[]{50, 100, 100};
combo = new DetailedComboBox(columns, widths, 0);
combo.setTableData(tableData);
combo.setSelectedIndex(-1);
combo.setPopupAlignment(DetailedComboBox.Alignment.LEFT);
combo.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDetails();
}
});
name = new JTextField(10);
capital = new JTextField(10);
name.setEditable(false);
capital.setEditable(false);
JPanel p = new JPanel(new FlowLayout());
p.add(new JLabel("State"));
p.add(combo);
p.add(new JLabel("Name"));
p.add(name);
p.add(new JLabel("Capital"));
p.add(capital);
JFrame frame = new JFrame("DetailedComboBox Demo");
frame.getContentPane().add(p, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void showDetails()
{
List<? extends Object> rowData = combo.getSelectedRow();
name.setText(rowData.get(1).toString());
capital.setText(rowData.get(2).toString());
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new DetailedComboBoxDemo());
}
}
这篇关于Java Swing的多列自动完成组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!