Adding/Removing 列基于菜单选择
Adding/Removing columns based on menu selection
我有一个 JTable;我想提供一个带有复选框的菜单,table 中的每一列都有一个复选框,以允许用户对 select 列进行显示或隐藏。我写了下面的 class,几乎可以工作。
public class SelectableColumns implements ActionListener
{
JTable table = null;
JMenu menu = null; public JMenu getMenu() { return menu; }
public SelectableColumns(JTable table)
{
this.table = table;
menu = new JMenu("Columns");
TableColumnModel columnModel = table.getColumnModel();
Enumeration<TableColumn> enumerator = columnModel.getColumns();
while (enumerator.hasMoreElements())
{
TableColumn column = enumerator.nextElement();
String headerName = column.getHeaderValue().toString();
JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(headerName, true);
cbmi.addActionListener(this);
column.setIdentifier(cbmi);
menu.add(cbmi);
}
}
@Override
public void actionPerformed(ActionEvent e)
{
JCheckBoxMenuItem source = (JCheckBoxMenuItem)e.getSource();
boolean checked = source.getState();
TableColumnModel columnModel = table.getColumnModel();
int columnIndex = columnModel.getColumnIndex(source); // <<-- fails after removing the column
System.out.printf("Checked: %b, column: %d%n", checked, columnIndex);
TableColumn column = columnModel.getColumn(columnIndex);
if (checked)
{
// add this column back to the table
table.addColumn(column);
int displayedColumns = getDisplayedColumns(columnModel);
table.moveColumn(displayedColumns, displayedColumns-1);
}
else
{
// remove this column from the table
table.removeColumn(column);
}
}
private int getDisplayedColumns(TableColumnModel columnModel)
{
Enumeration<TableColumn> columns = columnModel.getColumns();
int displayedCount = 0;
while (columns.hasMoreElements())
{
displayedCount++;
}
return displayedCount;
}
}
我遇到的问题是,一旦我删除了该列,它就不再存在于 TableColumnModel 中;我希望该列位于 TableColumnModel 中,但不再位于 JTable 中。
但是我弄错了:方法TableColumnModel.getColumn(int index)
在显示列时起作用,显示列后就失效了。当我在调试器中检查 TableColumnModel 实例时,很明显该列已从模型中删除。
有没有办法做我想做的事?我可以制作一组列以重新插入丢失的列,但我阅读的一些文档让我相信 table 只是模型的一个视图,所以我坚持相信专栏就在某处。谁能告诉我在哪里可以找到它?
非常感谢 camickr;我以为我会 post class 结果是:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* Holds representation of columns from the given JTable, including
* a JMenu and its action routine for removing them and replacing
* them in the table.
* <P>To use, create an instance with your table after
* it has at least enough data to establish its columns. Then use
* getMenu() for an instance of JMenu, and put it on your menu bar.
* The resulting menu will have checkboxes for all the columns, and
* it handles their removal and addition. No other code in the application
* should remove or add columns; their added/removal state is maintained
* in the SelectableColumns instance.
*
* @author rcook
*/
public class SelectableColumns implements ActionListener
{
JTable table = null;
JMenu menu = null; public JMenu getMenu() { return menu; }
ArrayList<TableColumn> removedColumns = new ArrayList<TableColumn>();
public SelectableColumns(JTable table)
{
this.table = table;
menu = new JMenu("Columns");
TableColumnModel columnModel = table.getColumnModel();
Enumeration<TableColumn> enumerator = columnModel.getColumns();
while (enumerator.hasMoreElements())
{
TableColumn column = enumerator.nextElement();
String headerName = column.getHeaderValue().toString();
JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(headerName, true);
cbmi.addActionListener(this);
column.setIdentifier(cbmi);
menu.add(cbmi);
}
}
/**
* A Checkbox menu item representing one column has been chosen; it
* could have been checked or unchecked. Put the removed column
* back into the table, or remove it from the table.
*/
@Override
public void actionPerformed(ActionEvent e)
{
JCheckBoxMenuItem source = (JCheckBoxMenuItem)e.getSource();
TableColumnModel columnModel = table.getColumnModel();
boolean checked = source.getState();
TableColumn removedColumn = null;
if (!checked)
{
// remove this column from the table
int columnIndex = columnModel.getColumnIndex(source);
//System.out.printf("Checked: %b, column: %d%n", checked, columnIndex);
TableColumn column = columnModel.getColumn(columnIndex);
table.removeColumn(column);
removedColumns.add(column);
}
else
{
// add this column back to the table
// first find the column in the list of removed columns
for (TableColumn column: removedColumns)
{
if (column.getIdentifier().equals(source))
{
removedColumn = column;
break;
}
}
// as long as we actually have a column, add it back to the
// table
if (removedColumn == null)
{
System.err.println("removedColumn not in the list...");
}
else
{
table.addColumn(removedColumn);
int numDisplayed = columnModel.getColumnCount();
table.moveColumn(numDisplayed-1, numDisplayed-2); // move to next-to-last position
removedColumns.remove(removedColumn);
}
}
}
}
我只是添加了一个 "removed columns" 的列表,并用它来添加重新检查显示的任何已删除的列。我总是添加到倒数第二个位置;显然,对于一般用途,这可以变得更加灵活。我还想过有一种方法可以显示带有复选框的对话框,因此用户可以一次更改多个列的状态。但是对于 100 行代码,这就是我现在想要的,并说明了我一直在寻找的原理,并且是 camickr 友情提供的。
Is there a way to do what I want? I can make a collection of columns to re-insert the one that is missing,
正确,您需要跟踪删除的 TableColumns。然后,您的弹出菜单需要根据 TableColumn 是在 TableColumnModel 中还是在已删除的 TableColumns 集合中来设置复选框的状态。
或者您可以使用已经为您提供此功能的 Table Column Manager。
此实现还尝试在删除列时跟踪该列的位置,以便将其插回到同一位置,而不是仅仅将其附加到 TableColumnModel 的末尾。
我有一个 JTable;我想提供一个带有复选框的菜单,table 中的每一列都有一个复选框,以允许用户对 select 列进行显示或隐藏。我写了下面的 class,几乎可以工作。
public class SelectableColumns implements ActionListener
{
JTable table = null;
JMenu menu = null; public JMenu getMenu() { return menu; }
public SelectableColumns(JTable table)
{
this.table = table;
menu = new JMenu("Columns");
TableColumnModel columnModel = table.getColumnModel();
Enumeration<TableColumn> enumerator = columnModel.getColumns();
while (enumerator.hasMoreElements())
{
TableColumn column = enumerator.nextElement();
String headerName = column.getHeaderValue().toString();
JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(headerName, true);
cbmi.addActionListener(this);
column.setIdentifier(cbmi);
menu.add(cbmi);
}
}
@Override
public void actionPerformed(ActionEvent e)
{
JCheckBoxMenuItem source = (JCheckBoxMenuItem)e.getSource();
boolean checked = source.getState();
TableColumnModel columnModel = table.getColumnModel();
int columnIndex = columnModel.getColumnIndex(source); // <<-- fails after removing the column
System.out.printf("Checked: %b, column: %d%n", checked, columnIndex);
TableColumn column = columnModel.getColumn(columnIndex);
if (checked)
{
// add this column back to the table
table.addColumn(column);
int displayedColumns = getDisplayedColumns(columnModel);
table.moveColumn(displayedColumns, displayedColumns-1);
}
else
{
// remove this column from the table
table.removeColumn(column);
}
}
private int getDisplayedColumns(TableColumnModel columnModel)
{
Enumeration<TableColumn> columns = columnModel.getColumns();
int displayedCount = 0;
while (columns.hasMoreElements())
{
displayedCount++;
}
return displayedCount;
}
}
我遇到的问题是,一旦我删除了该列,它就不再存在于 TableColumnModel 中;我希望该列位于 TableColumnModel 中,但不再位于 JTable 中。
但是我弄错了:方法TableColumnModel.getColumn(int index)
在显示列时起作用,显示列后就失效了。当我在调试器中检查 TableColumnModel 实例时,很明显该列已从模型中删除。
有没有办法做我想做的事?我可以制作一组列以重新插入丢失的列,但我阅读的一些文档让我相信 table 只是模型的一个视图,所以我坚持相信专栏就在某处。谁能告诉我在哪里可以找到它?
非常感谢 camickr;我以为我会 post class 结果是:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* Holds representation of columns from the given JTable, including
* a JMenu and its action routine for removing them and replacing
* them in the table.
* <P>To use, create an instance with your table after
* it has at least enough data to establish its columns. Then use
* getMenu() for an instance of JMenu, and put it on your menu bar.
* The resulting menu will have checkboxes for all the columns, and
* it handles their removal and addition. No other code in the application
* should remove or add columns; their added/removal state is maintained
* in the SelectableColumns instance.
*
* @author rcook
*/
public class SelectableColumns implements ActionListener
{
JTable table = null;
JMenu menu = null; public JMenu getMenu() { return menu; }
ArrayList<TableColumn> removedColumns = new ArrayList<TableColumn>();
public SelectableColumns(JTable table)
{
this.table = table;
menu = new JMenu("Columns");
TableColumnModel columnModel = table.getColumnModel();
Enumeration<TableColumn> enumerator = columnModel.getColumns();
while (enumerator.hasMoreElements())
{
TableColumn column = enumerator.nextElement();
String headerName = column.getHeaderValue().toString();
JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(headerName, true);
cbmi.addActionListener(this);
column.setIdentifier(cbmi);
menu.add(cbmi);
}
}
/**
* A Checkbox menu item representing one column has been chosen; it
* could have been checked or unchecked. Put the removed column
* back into the table, or remove it from the table.
*/
@Override
public void actionPerformed(ActionEvent e)
{
JCheckBoxMenuItem source = (JCheckBoxMenuItem)e.getSource();
TableColumnModel columnModel = table.getColumnModel();
boolean checked = source.getState();
TableColumn removedColumn = null;
if (!checked)
{
// remove this column from the table
int columnIndex = columnModel.getColumnIndex(source);
//System.out.printf("Checked: %b, column: %d%n", checked, columnIndex);
TableColumn column = columnModel.getColumn(columnIndex);
table.removeColumn(column);
removedColumns.add(column);
}
else
{
// add this column back to the table
// first find the column in the list of removed columns
for (TableColumn column: removedColumns)
{
if (column.getIdentifier().equals(source))
{
removedColumn = column;
break;
}
}
// as long as we actually have a column, add it back to the
// table
if (removedColumn == null)
{
System.err.println("removedColumn not in the list...");
}
else
{
table.addColumn(removedColumn);
int numDisplayed = columnModel.getColumnCount();
table.moveColumn(numDisplayed-1, numDisplayed-2); // move to next-to-last position
removedColumns.remove(removedColumn);
}
}
}
}
我只是添加了一个 "removed columns" 的列表,并用它来添加重新检查显示的任何已删除的列。我总是添加到倒数第二个位置;显然,对于一般用途,这可以变得更加灵活。我还想过有一种方法可以显示带有复选框的对话框,因此用户可以一次更改多个列的状态。但是对于 100 行代码,这就是我现在想要的,并说明了我一直在寻找的原理,并且是 camickr 友情提供的。
Is there a way to do what I want? I can make a collection of columns to re-insert the one that is missing,
正确,您需要跟踪删除的 TableColumns。然后,您的弹出菜单需要根据 TableColumn 是在 TableColumnModel 中还是在已删除的 TableColumns 集合中来设置复选框的状态。
或者您可以使用已经为您提供此功能的 Table Column Manager。
此实现还尝试在删除列时跟踪该列的位置,以便将其插回到同一位置,而不是仅仅将其附加到 TableColumnModel 的末尾。