Mehrere TableModels zu einem einzigen zusammenfügen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen

RangeTableModel

Mit folgendem Code kann man mehrere TableModels zu einem zusammenfügen, oder bestimmte Zeilen/Spaltenmengen aus einem bestehenden TableModel als ein neues, eigenständiges TableModel anbieten.
Trivialkram, aber immerhin braucht jemand, der das braucht, diesen Trivialkram dann nicht mehr selbst zu schreiben.

<code=java> import java.util.*; import javax.swing.event.*; import javax.swing.table.*;

/**

* This class provides utility methods to create special TableModels
* that are composed of other TableModels, or consist of selected
* subsets of rows and columns of other TableModels
*/

class TableModelUtils {

   /**
    * Creates a TableModel that composes the given TableModels into
    * one. The number of rows of the resulting TableModel will be
    * the maximum of all row counts of the given TableModels
    *
    * @param tableModels The TableModels to combine
    * @return A TableModel combining the given TableModels
    */
   public static TableModel createCompoundTableModel(TableModel ... tableModels)
   {
       return new CompoundTableModel(tableModels);
   }
   /**
    * Creates a new TableModel which represents the "sub-table" that is
    * described by the given row- and column indices
    *
    * @param tableModel The TableModel from which the given sub-table
    * should be taken
    * @param col0 The first column of the sub-table, i.e. index of the
    * column in the given TableModel that should be the column with
    * index 0 in the returned model
    * @param row0 The first row of the sub-table, i.e. index of the
    * row in the given TableModel that should be the row with
    * index 0 in the returned model
    * @param col1 The column index where the sub-table should end
    * @param row1 The row index where the sub-table should end
    * @return A sub-table of the given TableModel
    */
   public static RangeTableModel createSubTableModel(TableModel tableModel, int row0, int col0, int row1, int col1)
   {
       return new RangeTableModel(tableModel, row0, col0, row1, col1);
   }
   /**
    * Creates a TableModel that consists of the rows with the
    * given indices of the given TableModel
    *
    * @param tableModel The TableModel from which the rows
    * will be taken
    * @param indices The indices of the rows that should be
    * contained in the resulting TableModel
    * @return
    */
   public static TableModel createRowSelectionTableModel(TableModel tableModel, int ... indices)
   {
       return new SelectionTableModel(tableModel, indices, null);
   }
   /**
    * Creates a TableModel that consists of the columns with the
    * given indices of the given TableModel
    *
    * @param tableModel The TableModel from which the columns
    * will be taken
    * @param indices The indices of the columns that should be
    * contained in the resulting TableModel
    * @return
    */
   public static TableModel createColumnSelectionTableModel(TableModel tableModel, int ... indices)
   {
       return new SelectionTableModel(tableModel, null, indices);
   }


   /**
    * This class is a TableModel that combines several other TableModels
    */
   private static class CompoundTableModel implements TableModel
   {
       /**
        * The TableModels that are combined in this TableModel
        */
       private List<TableModel> tableModels;
       /**
        * Create a new CompoundTableModel, combining the given TableModels
        *
        * @param tableModels The TableModels to combine
        */
       public CompoundTableModel(TableModel ... tableModels)
       {
           this.tableModels = new ArrayList<TableModel>(Arrays.asList(tableModels));
       }
       /**
        * {@inheritDoc}
        */
       public void addTableModelListener(TableModelListener tableModelListener)
       {
           for (TableModel tableModel : tableModels)
           {
               tableModel.addTableModelListener(tableModelListener);
           }
       }
       /**
        * {@inheritDoc}
        */
       public void removeTableModelListener(TableModelListener tableModelListener)
       {
           for (TableModel tableModel : tableModels)
           {
               tableModel.removeTableModelListener(tableModelListener);
           }
       }


       /**
        * {@inheritDoc}
        */
       public Class getColumnClass(int columnIndex)
       {
           for (TableModel tableModel : tableModels)
           {
               if (tableModel.getColumnCount() > columnIndex)
               {
                   return tableModel.getColumnClass(columnIndex);
               }
               columnIndex -= tableModel.getColumnCount();
           }
           throw new IllegalArgumentException("No column found for the given index");
       }
       /**
        * {@inheritDoc}
        */
       public int getColumnCount()
       {
           int columnCount = 0;
           for (TableModel tableModel : tableModels)
           {
               columnCount += tableModel.getColumnCount();
           }
           return columnCount;
       }
       /**
        * {@inheritDoc}
        */
       public String getColumnName(int columnIndex)
       {
           for (TableModel tableModel : tableModels)
           {
               if (tableModel.getColumnCount() > columnIndex)
               {
                   return tableModel.getColumnName(columnIndex);
               }
               columnIndex -= tableModel.getColumnCount();
           }
           throw new IllegalArgumentException("No column found for the given index");
       }


       /**
        * {@inheritDoc}
        */
       public int getRowCount()
       {
           int maxRowCount = -1;
           for (TableModel tableModel : tableModels)
           {
               maxRowCount = Math.max(maxRowCount, tableModel.getRowCount());
           }
           return maxRowCount;
       }
       /**
        * {@inheritDoc}
        */
       public Object getValueAt(int rowIndex, int columnIndex)
       {
           for (TableModel tableModel : tableModels)
           {
               if (tableModel.getColumnCount() > columnIndex)
               {
                   if (rowIndex < tableModel.getRowCount())
                   {
                       return tableModel.getValueAt(rowIndex, columnIndex);
                   }
                   else
                   {
                       return null;
                   }
               }
               columnIndex -= tableModel.getColumnCount();
           }
           throw new IllegalArgumentException("No column found for the given index");
       }
       /**
        * {@inheritDoc}
        */
       public void setValueAt(Object aValue, int rowIndex, int columnIndex)
       {
           for (TableModel tableModel : tableModels)
           {
               if (tableModel.getColumnCount() > columnIndex)
               {
                   if (rowIndex < tableModel.getRowCount())
                   {
                       tableModel.setValueAt(aValue, rowIndex, columnIndex);
                   }
                   else
                   {
                       throw new IllegalArgumentException("No cell found for the given row index");
                   }
               }
               columnIndex -= tableModel.getColumnCount();
           }
           throw new IllegalArgumentException("No column found for the given index");
       }


       /**
        * {@inheritDoc}
        */
       public boolean isCellEditable(int rowIndex, int columnIndex)
       {
           for (TableModel tableModel : tableModels)
           {
               if (tableModel.getColumnCount() > columnIndex)
               {
                   if (rowIndex < tableModel.getRowCount())
                   {
                       return tableModel.isCellEditable(rowIndex, columnIndex);
                   }
                   else
                   {
                       return false;
                   }
               }
               columnIndex -= tableModel.getColumnCount();
           }
           throw new IllegalArgumentException("No column found for the given index");
       }
   }


   /**
    * This class describes a TableModel which represents a selection
    * of rows and columns of another TableModel
    */
   private static class SelectionTableModel implements TableModel
   {
       /**
        * The TableModel from which the rows and columns are selected
        */
       private TableModel tableModel;
       /**
        * The selection of rows
        */
       private int rowSelection[];
       /**
        * The selection of columns
        */
       private int columnSelection[];
       /**
        * Creates a new SelectionTableModel, which selects the specified rows
        * and columns from the given TableModel. The selections may be null.
        * Then all rows/columns will be selected, respectively
        *
        * @param tableModel The TableModel from which the rows and columns are selected
        * @param rowSelection The selection of rows
        * @param columnSelection The selection of columns
        */
       public SelectionTableModel(TableModel tableModel, int rowSelection[], int columnSelection[])
       {
           this.tableModel = tableModel;
           if (rowSelection != null)
           {
               this.rowSelection = rowSelection.clone();
           }
           else
           {
               this.rowSelection = createSelectionFromSize(tableModel.getRowCount());
           }
           if (columnSelection != null)
           {
               this.columnSelection = columnSelection.clone();
           }
           else
           {
               this.columnSelection = createSelectionFromSize(tableModel.getColumnCount());
           }
       }
       /**
        * Creates a selection containing all indices from 0 to size-1
        *
        * @param size The size of the selection
        * @return The selection array
        */
       static int[] createSelectionFromSize(int size)
       {
           int selected[] = new int[size];
           for (int i=0; i<selected.length; i++)
           {
               selected[i] = i;
           }
           return selected;
       }
       /**
        * Creates a selection containing all indices from min to max-1
        *
        * @param min The minimum value to be selected
        * @param max The maximum value to be selected
        * @return The selection array
        */
       static int[] createSelectionFromRange(int min, int max)
       {
           int selected[] = new int[max-min];
           for (int i=0; i<selected.length; i++)
           {
               selected[i] = i + min;
           }
           return selected;
       }


       /**
        * {@inheritDoc}
        */
       public void addTableModelListener(TableModelListener tableModelListener)
       {
           tableModel.addTableModelListener(tableModelListener);
       }
       /**
        * {@inheritDoc}
        */
       public void removeTableModelListener(TableModelListener tableModelListener)
       {
           tableModel.removeTableModelListener(tableModelListener);
       }
       /**
        * {@inheritDoc}
        */
       public Class getColumnClass(int columnIndex)
       {
           return tableModel.getColumnClass(columnSelection[columnIndex]);
       }
       /**
        * {@inheritDoc}
        */
       public int getColumnCount()
       {
           return columnSelection.length;
       }
       /**
        * {@inheritDoc}
        */
       public String getColumnName(int columnIndex)
       {
           return tableModel.getColumnName(columnSelection[columnIndex]);
       }
       /**
        * {@inheritDoc}
        */
       public int getRowCount()
       {
           return rowSelection.length;
       }
       /**
        * {@inheritDoc}
        */
       public Object getValueAt(int rowIndex, int columnIndex)
       {
           return tableModel.getValueAt(rowSelection[rowIndex], columnSelection[columnIndex]);
       }
       /**
        * {@inheritDoc}
        */
       public void setValueAt(Object aValue, int rowIndex, int columnIndex)
       {
           tableModel.setValueAt(aValue, rowSelection[rowIndex], columnSelection[columnIndex]);
       }


       /**
        * {@inheritDoc}
        */
       public boolean isCellEditable(int rowIndex, int columnIndex)
       {
           return tableModel.isCellEditable(rowSelection[rowIndex], columnSelection[columnIndex]);
       }
   }


   /**
    * This class describes a TableModel which represents a range
    * of rows and columns of another TableModel
    */
   public static class RangeTableModel implements TableModel
   {
       /**
        * The TableModel from which the rows and columns are selected
        */
       private TableModel tableModel;


       /**
        * The TableModelListeners that have been added to this TableModel
        */
       private List<TableModelListener> tableModelListeners = new ArrayList<TableModelListener>();
       /**
        * The minimum row
        */
       private int minRow;
       /**
        * The maximum row
        */
       private int maxRow;
       /**
        * The minimum column
        */
       private int minColumn;
       /**
        * The maximum column
        */
       private int maxColumn;
       /**
        * Creates a new SelectionTableModel, which selects the specified rows
        * and columns from the given TableModel.
        *
        * @param tableModel The TableModel from which the rows and columns are selected
        * @param minRow The row of the given model which will be row 0 in this model
        * @param minColumn The column of the given model which will be column 0 in this model
        * @param maxRow The row of the given model which will be the last row in this model
        * @param maxColumn The column of the given model which will be the last column in this model
        */
       public RangeTableModel(TableModel tableModel, int minRow, int minColumn, int maxRow, int maxColumn)
       {
           this.tableModel = tableModel;
           this.minRow = minRow;
           this.maxRow = maxRow;
           this.minColumn = minColumn;
           this.maxColumn = maxColumn;
       }


       /**
        * Set the range that is displayed by this RangeTableModel.
        *
        * @param minRow The row of the given model which will be row 0 in this model
        * @param minColumn The column of the given model which will be column 0 in this model
        * @param maxRow The row of the given model which will be the last row in this model
        * @param maxColumn The column of the given model which will be the last column in this model
        */
       public void setRange(int minRow, int minColumn, int maxRow, int maxColumn)
       {
           this.minRow = minRow;
           this.maxRow = maxRow;
           this.minColumn = minColumn;
           this.maxColumn = maxColumn;
           if (tableModelListeners.size() > 0)
           {
               TableModelEvent tableModelEvent = new TableModelEvent(this, TableModelEvent.HEADER_ROW);
               for (TableModelListener tableModelListener : tableModelListeners)
               {
                   tableModelListener.tableChanged(tableModelEvent);
               }
           }
       }


       /**
        * {@inheritDoc}
        */
       public void addTableModelListener(TableModelListener tableModelListener)
       {
           tableModel.addTableModelListener(tableModelListener);
           tableModelListeners.add(tableModelListener);
       }
       /**
        * {@inheritDoc}
        */
       public void removeTableModelListener(TableModelListener tableModelListener)
       {
           tableModel.removeTableModelListener(tableModelListener);
           tableModelListeners.remove(tableModelListener);
       }
       /**
        * {@inheritDoc}
        */
       public Class getColumnClass(int columnIndex)
       {
           return tableModel.getColumnClass(columnIndex+minColumn);
       }
       /**
        * {@inheritDoc}
        */
       public int getColumnCount()
       {
           return maxColumn - minColumn + 1;
       }
       /**
        * {@inheritDoc}
        */
       public String getColumnName(int columnIndex)
       {
           return tableModel.getColumnName(columnIndex+minColumn);
       }
       /**
        * {@inheritDoc}
        */
       public int getRowCount()
       {
           return maxRow - minRow + 1;
       }
       /**
        * {@inheritDoc}
        */
       public Object getValueAt(int rowIndex, int columnIndex)
       {
           return tableModel.getValueAt(rowIndex + minRow, columnIndex + minColumn);
       }
       /**
        * {@inheritDoc}
        */
       public void setValueAt(Object aValue, int rowIndex, int columnIndex)
       {
           tableModel.setValueAt(aValue, rowIndex + minRow, columnIndex + minColumn);
       }


       /**
        * {@inheritDoc}
        */
       public boolean isCellEditable(int rowIndex, int columnIndex)
       {
           return tableModel.isCellEditable(rowIndex + minRow, columnIndex + minColumn);
       }
   }

} </code=java>


Und noch ein kleines Testprogram... <code=java> import java.util.*; import java.util.List;

import javax.swing.event.*; import javax.swing.table.TableModel;

import java.awt.*; import javax.swing.*; import javax.swing.table.*;

/**

* Test class for the TableModelUtils
*/

class TableModelUtilsTest extends JFrame {

   public static void main(String args[])
   {
       new TableModelUtilsTest();
   }
   public TableModelUtilsTest()
   {
       super("TableModelUtils test");
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


       TableModel tm0 = new DefaultTableModel(
           new Object[][] {
               { "tm0 c00", "tm0 c01", "tm0 c02" },
               { "tm0 c10", "tm0 c11", "tm0 c12" },
               { "tm0 c20", "tm0 c21", "tm0 c22" } },
           new Object[]
               { "tm0 h0", "tm0 h1", "tm0 h2" });
       TableModel tm1 = new DefaultTableModel(
           new Object[][] {
               { "tm1 c00", "tm1 c01", "tm1 c02", "tm1 c03", "tm1 c04" },
               { "tm1 c10", "tm1 c11", "tm1 c12", "tm1 c13", "tm1 c14" },
               { "tm1 c20", "tm1 c21", "tm1 c22", "tm1 c23", "tm1 c24" },
               { "tm1 c30", "tm1 c31", "tm1 c32", "tm1 c33", "tm1 c34" },
               { "tm1 c40", "tm1 c41", "tm1 c42", "tm1 c43", "tm1 c44" } },
           new Object[]
               { "tm1 h0", "tm1 h1", "tm1 h2", "tm1 h3" , "tm1 h4" });


       JPanel p = new JPanel();
       p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
       p.add(createPanel("Input model 0", tm0));
       p.add(createPanel("Input model 1", tm1));
       p.add(createRangePanel(TableModelUtils.createSubTableModel(tm1, 0,0,4,4)));
       p.add(createPanel("Compound of model 0 and model 1",
                         TableModelUtils.createCompoundTableModel(tm0, tm1)));
       p.add(createPanel("Sub(1,1,4,4) of model 1",
                         TableModelUtils.createSubTableModel(tm1, 1,1,4,4)));
       p.add(createPanel("RowSelection(0,2,4) of model 1",
                         TableModelUtils.createRowSelectionTableModel(tm1, 0,2,4)));
       p.add(createPanel("ColumnSelection(0,2,4) of model 1",
                         TableModelUtils.createColumnSelectionTableModel(tm1, 0,2,4)));
       TableModel tableModel = null;
       tableModel = TableModelUtils.createCompoundTableModel(tm0, tm1);
       tableModel = TableModelUtils.createSubTableModel(tableModel, 1,1,4,5);
       tableModel = TableModelUtils.createRowSelectionTableModel(tableModel, 0,2);
       tableModel = TableModelUtils.createColumnSelectionTableModel(tableModel, 0,2,4);
       p.add(createPanel("<html>ColumnSelection(0,2,4) of "+"RowSelection(0,2) of " +
                         "Sub(1,1,4,4) of " + "Compound of model 0 and model 1",tableModel));
       getContentPane().add(new JScrollPane(p));
       setSize(800,300);
       setVisible(true);
   }
   private JPanel createPanel(String infoString, TableModel tableModel)
   {
       JPanel panel = new JPanel(new BorderLayout());
       JLabel label = new JLabel(infoString);
       panel.add(label, BorderLayout.NORTH);
       panel.add(new JScrollPane(new JTable(tableModel)), BorderLayout.CENTER);
       return panel;
   }


   private JPanel createRangePanel(final TableModelUtils.RangeTableModel tableModel)
   {
       JPanel panel = new JPanel(new BorderLayout());


       JPanel p = new JPanel(new BorderLayout());
       p.add(new JLabel("Selection of range"), BorderLayout.NORTH);
       JPanel controlPanel = new JPanel(new GridLayout(2,0));
       final JSpinner minRow = createSpinner(0, 0, tableModel.getRowCount()-1);
       final JSpinner minCol = createSpinner(0, 0, tableModel.getColumnCount()-1);
       final JSpinner maxRow = createSpinner(tableModel.getRowCount()-1, 0, tableModel.getRowCount()-1);
       final JSpinner maxCol = createSpinner(tableModel.getColumnCount()-1, 0, tableModel.getColumnCount()-1);
       ChangeListener changeListener = new ChangeListener()
       {
           public void stateChanged(ChangeEvent e)
           {
               int minR = (Integer)minRow.getValue();
               int minC = (Integer)minCol.getValue();
               int maxR = (Integer)maxRow.getValue();
               int maxC = (Integer)maxCol.getValue();
               tableModel.setRange(minR, minC, maxR, maxC);
           }
       };
       minRow.addChangeListener(changeListener);
       minCol.addChangeListener(changeListener);
       maxRow.addChangeListener(changeListener);
       maxCol.addChangeListener(changeListener);
       controlPanel.add(new JLabel("Min. row", JLabel.CENTER));
       controlPanel.add(minRow);
       controlPanel.add(new JLabel("Min. col", JLabel.CENTER));
       controlPanel.add(minCol);
       controlPanel.add(new JLabel("Max. row", JLabel.CENTER));
       controlPanel.add(maxRow);
       controlPanel.add(new JLabel("Max. col", JLabel.CENTER));
       controlPanel.add(maxCol);
       p.add(controlPanel, BorderLayout.CENTER);
       panel.add(p, BorderLayout.NORTH);
       panel.add(new JScrollPane(new JTable(tableModel)), BorderLayout.CENTER);
       return panel;
   }
   private JSpinner createSpinner(int initial, int min, int max)
   {
       SpinnerModel model = new SpinnerNumberModel(initial, min, max, 1);
       JSpinner spinner = new JSpinner(model);
       return spinner;
   }

} </code=java>


Nachbetrachtung

Eigentlich wär's ja noch schick, das ganze in dem Sinne "mächtiger" zu machen, dass man sowas wie die hintereinanderschaltbaren {JAPI|RowFilter} (und entsprechende {JAPI|ColumnFilter}) einbaut, aber ... da das ja keiner braucht.... </code=java> --Marco13 27.08.2008, 19:39