我想要一个对话框,为JTable
中的数据指定过滤器。该对话框将有第二个JTable
;其中一列将代表过滤器适用的第一个JTable
中的列;其他列之一将是用于过滤的字符串。
我在真实应用中的第二个JTable
中有其他列 - 过滤器是否确保字符串存在或不存在等等 - 但这些对问题并不重要。
我为TableColumn
创建并安装了自定义渲染器和编辑器,并为TableColumn
类注册了第二个表;我希望表示第二个表中列的字符串是TableColumn
的标题,并且能够引用实际的TableColumn
作为正在编辑的项目。
在我到目前为止的代码中,当我第一次显示带有一行伪数据的对话框时,确实显示了伪数据中列的标题值。但是,当我单击该值时,每列的下拉值是执行tableColumn.toString()
时获得的字符串。
构建单元格编辑器下拉列表的代码会将TableColumn
值放在JComboBox<TableColumn>
中,正如我认为的那样;如何让编辑器使用tableColumn中的标头值而不是使用它的toString(),或者它正在做什么?
还有一件事:在真实应用中,第一个JTable
中的列是动态的;我不能简单地列出代码中的列。我从数据中导出列数及其标题。请不要只给我一些例子,假设要编辑的列是提前知道的。如果有人可以解释它是如何工作而不只是举例,那就太棒了,但如果我们必须完全通过例子进行沟通,请包括表格的动态性质。
package lincoln.ui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
@SuppressWarnings("serial")
public class ExampleColumnCombo extends JFrame
{
private JButton getDialogButton = null;
public static void main(String ... arguments)
{
ExampleColumnCombo me = new ExampleColumnCombo();
me.go(arguments);
}
private void go(String ... arguments)
{
createUI(this);
setVisible(true);
}
// defines one filter test: each item defines a column to test
// and the value to test in it.
class FilterItem
{
private TableColumn column = null;
private String targetString = null;
public FilterItem (TableColumn tc, String targetString)
{
column = tc;
this.targetString = targetString;
}
public TableColumn getColumn() { return column; }
public String getTargetString() { return targetString; }
}
private void createUI(final ExampleColumnCombo mainFrame)
{
Object[][] data = { { "color", "red" }, {"shape", "square"}, {"fruit", "banana"}, {"plain", "text"}};
String[] columnNames = {"type", "value" };
DefaultTableModel model = new DefaultTableModel(data, columnNames);
final JTable table = new JTable(model);
getDialogButton = new JButton("filters");
getDialogButton.addActionListener
(
new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
FilterModel filterModel = new FilterModel();
filterModel.addItem(new FilterItem(table.getColumnModel().getColumn(0), "color"));
FilterDialog dialog = new FilterDialog(mainFrame, filterModel);
dialog.setVisible(true);
}
}
);
JPanel upperPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
upperPanel.add(getDialogButton);
add(upperPanel, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,300);
setLocationByPlatform(true);
}
class FilterModel extends AbstractTableModel
{
private ArrayList<FilterItem> filters = new ArrayList<>();
public int getColumnCount() { return 2; }
public boolean isCellEditable(int row, int column) { return true; }
public Class<?> getColumnClass(int i)
{
switch (i)
{
case 0: return TableColumn.class;
case 1: return String.class;
default: System.err.println("error, bad column given for class");
}
return null;
}
@Override
public int getRowCount() { return filters.size(); }
@Override
public Object getValueAt(int rowIndex, int columnIndex)
{
FilterItem item = filters.get(rowIndex);
switch(columnIndex)
{
case 0: return item.getColumn(); //break;
case 1: return item.getTargetString(); //break;
default: System.err.println("wrong"); new Exception().printStackTrace(); break;
}
return null;
}
public void addItem(FilterItem item)
{
filters.add(item);
}
}
class FilterDialog extends JDialog
{
public FilterDialog(ExampleColumnCombo mainDisplay,
final FilterModel filterModel)
{
JTable table = new JTable(filterModel);
table.setDefaultRenderer(TableColumn.class, new TableColumnCellRenderer());
table.setDefaultEditor(TableColumn.class, new TableColumnCellEditor());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
setSize(200,200);
pack();
setVisible(true);
}
}
class TableColumnCellEditor extends AbstractCellEditor implements
TableCellEditor, ActionListener
{
private TableColumn tableColumn;
public TableColumnCellEditor() {}
@Override
public Object getCellEditorValue()
{
return tableColumn;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int col)
{
if (value instanceof TableColumn)
{
tableColumn = (TableColumn)value;
}
JComboBox<TableColumn> comboTableColumnType = new JComboBox<>();
Enumeration<TableColumn> columnEnumeration = table.getColumnModel().getColumns();
while (columnEnumeration.hasMoreElements())
{
TableColumn column = (TableColumn)columnEnumeration.nextElement();
comboTableColumnType.addItem(column);
}
comboTableColumnType.setSelectedItem(value);
comboTableColumnType.addActionListener(this);
return comboTableColumnType;
}
@Override
public void actionPerformed(ActionEvent e)
{
@SuppressWarnings("unchecked")
JComboBox<TableColumn> comboTableColumnType = (JComboBox<TableColumn>) e.getSource();
this.tableColumn = (TableColumn)comboTableColumnType.getSelectedItem();
}
@Override
public String toString()
{
return this.tableColumn.getHeaderValue().toString();
}
}
public class TableColumnCellRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column)
{
if (value instanceof TableColumn)
{
TableColumn tableColumn = (TableColumn) value;
Object o = tableColumn.getHeaderValue();
setText((String)o);
}
return this;
}
}
}
答案 0 :(得分:2)
一种方法是使用JComboBox<String>
作为编辑器,并使用getHeaderValue().toString()
返回的结果填充其模型。
JComboBox<String> comboTableColumnType = new JComboBox<>();
Enumeration<TableColumn> columnEnumeration = table.getColumnModel().getColumns();
while (columnEnumeration.hasMoreElements()) {
TableColumn column = (TableColumn) columnEnumeration.nextElement();
comboTableColumnType.addItem(column.getHeaderValue().toString());
}
无需覆盖toString()
中的TableColumnCellEditor
。