我有一个包含几个自定义 JXTable(JTable 的扩展)的应用程序,这些 JXTable 已更新以反映存储在数据库中的信息。
我想在表格顶部的列标题上方添加组件,这将允许用户在表格中搜索和过滤结果。目前,我已经尝试使用 JTextFields 创建一个 JPanel,这些 JTextFields 基于附加到表的 TableColumnModelListener 和附加到每个 TableColumn 的 PropertyChangeListener 添加/删除/移动和调整大小。
这是它目前的样子:
我遇到的问题是我几乎对所有东西都使用了 jgoodies jforms 布局。在这个特定的面板中,我只是使用 BoxLayout,组件将(几乎)完美地调整大小,但是一旦我添加/删除列,就会开始推离屏幕或消失。
根据图像和我想要它做的事情,是否有人对 A)如何有效地将组件绑定到每列的位置/大小或 B)如何自定义表格的列并添加在它们之上的附加组件?
如果有帮助,这是代码:
private final KTable table;
private final ArrayList<Object> columnIds = new ArrayList<>();
private final ArrayList<JTextField> filters = new ArrayList<>();
private final PropertyChangeListener pcm = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()) {
case "width":
case "preferredWidth":
setFilterColumnWidth((TableColumn)evt.getSource(),
(int)evt.getNewValue());
break;
case "headerValue":
setFilterColumnName((TableColumn)evt.getSource(),
(String)evt.getNewValue());
break;
case "visible":
setFilterColumnVisible((TableColumn)evt.getSource(),
(boolean)evt.getNewValue());
break;
default:
System.out.println(evt.getPropertyName() + " : " + evt.getOldValue() + " | " + evt.getNewValue());
}
}
};
public KTableFilterPanel(KTable table) {
this.table = table;
registerListeners();
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
for (TableColumn column : table.getColumns()) {
addFilterColumn(column);
}
}
private void addFilterColumn(TableColumn column) {
addFilterColumn(column, -1);
}
private void addFilterColumn(TableColumn column, int index) {
Object id = column.getIdentifier();
if (columnIds.contains(id))
return;
JTextField filter = new JTextField(column.getHeaderValue().toString());
if (index == -1) {
columnIds.add(id);
filters.add(filter);
}
else {
columnIds.add(index, id);
filters.add(index, filter);
}
add(filter, filters.indexOf(filter));
revalidate();
}
private void removeFilterColumn(TableColumn column) {
Object id = column.getIdentifier();
if (!columnIds.contains(id))
return;
removeFilterColumn(columnIds.indexOf(id));
}
private void removeFilterColumn(int index) {
JTextField filter = filters.remove(index);
columnIds.remove(index);
remove(filter);
revalidate();
}
private void moveFilterColumn(int from, int to) {
if (from == to)
return;
Object id = columnIds.remove(from);
JTextField filter = filters.remove(from);
if (id == null || filter == null)
return;
columnIds.add(to, id);
filters.add(to, filter);
remove(filter);
add(filter, to);
revalidate();
}
private void setFilterColumnVisible(TableColumn column, boolean visible) {
Object id = column.getIdentifier();
if (!columnIds.contains(id))
return;
filters.get(columnIds.indexOf(id)).setVisible(visible);
revalidate();
}
private void setFilterColumnWidth(TableColumn column, int width) {
Object id = column.getIdentifier();
if (!columnIds.contains(id))
return;
JTextField filter = filters.get(columnIds.indexOf(id));
Dimension old = filter.getPreferredSize();
filter.setPreferredSize(new Dimension(width - 40, old.height));
revalidate();
}
private void setFilterColumnName(TableColumn column, String name) {
}
private void registerListeners() {
table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
TableColumn column = table.getColumnModel().getColumn(e.getToIndex());
addFilterColumn(column);
column.addPropertyChangeListener(pcm);
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
removeFilterColumn(e.getFromIndex());
}
@Override
public void columnMoved(TableColumnModelEvent e) {
moveFilterColumn(e.getFromIndex(), e.getToIndex());
}
@Override
public void columnMarginChanged(ChangeEvent e) {}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {}
});
}
非常感激!