データベースに格納されている情報を反映するように更新される、いくつかのカスタム JXTables (JTable の拡張機能) を持つアプリケーションがあります。
テーブルの上部、列ヘッダーの上にコンポーネントを追加して、ユーザーがテーブル内で結果を検索およびフィルタリングできるようにしたいと考えています。現在、テーブルに添付された TableColumnModelListener と各 TableColumn に添付された PropertyChangeListener に基づいて追加/削除/移動およびサイズ変更される JTextFields を使用して JPanel を作成しようとしました。
現在の様子は次のとおりです。
私が抱えている問題は、ほとんどすべてに 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) {}
});
}
とても有難い!