2015-09-05 6 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 строк кода это делает то, что я хочу прямо сейчас, и иллюстрирует принцип, который я искал, и этот камикр любезно предоставлен.

ответ

4

Есть ли способ сделать то, что я хочу? Я могу собрать коллекцию столбцов для повторной установки отсутствующего,

Правильно, вам нужно отслеживать Столбцы Столбцы, которые вы удаляете. Затем в вашем всплывающем меню необходимо установить состояние флажка в зависимости от того, находится ли TableColumn в TableColumnModel или в вашей коллекции удаленных табличных столбцов.

Или вы можете использовать Table Column Manager, который уже предоставляет эту функцию для вас.

Эта реализация также пытается отслеживать положение столбца при его удалении, чтобы его можно было вставить обратно в одно и то же место, а не просто добавить его в конец TableColumnModel.

Смежные вопросы