2015-09-05 21 views
0

我有一個JTable;我想提供一個帶複選框的菜單,表格中的每一列都有一個複選框,以允許用戶選擇要顯示或隱藏的列。我寫了下面的課,幾乎可以工作。基於菜單選擇添加/刪除列

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實例時,很明顯該列已從模型中刪除。

有沒有辦法做我想要的?我可以創建一個列的集合來重新插入缺少的列,但是我讀過的一些文檔讓我相信表只是模型的一個視圖,所以我堅持認爲列在那裏。誰能告訴我在哪裏可以找到它?


非常感謝camickr;我想我會後我結束了與類:

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); 
     } 
    } 
    } 

} 

我只是簡單地添加「刪除列」的列表,並用它來添加回任何刪除列被重新檢查,以顯示。我總是回到倒數第二的位置;顯然這對於​​一般用途來說可以更靈活。我也想過有一個方法可以顯示一個帶有複選框的對話框,這樣用戶就可以同時改變多個列的狀態。但是,對於100行代碼,這是我現在想要的,並說明了我正在尋找的原則以及camickr善意提供的原則。

回答

4

有沒有辦法做到我想要的?我可以使列的集合重新插入缺少的列,

正確,您需要跟蹤您刪除的TableColumns。然後,彈出式菜單需要根據TableColumn是在TableColumnModel還是在刪除的TableColumns集合中來設置複選框的狀態。

或者您可以使用已爲您提供此功能的Table Column Manager

此實現還會嘗試跟蹤列在刪除時的位置,以便可以將它插回到同一位置,而不是隻將其附加到TableColumnModel的末尾。