Creating a custom TableModel with multiple column headers and row headers

前端 未结 2 1357
醉酒成梦
醉酒成梦 2020-12-11 23:57

I\'m attempting to create a JTable that looks like the mockup below:

\"custom

The green corner

相关标签:
2条回答
  • 2020-12-12 00:39

    Input is limited to 20x20 so including the headers that's 22x22.

    Also consider a JScrollPane containing a JPanel having GridLayout and containing 22x22 instances JLabel, or a suitable subclass. This scales easily to several thousand cells.

    Addendum: If the need arises, CellRendererPane makes a good flyweight renderer, as suggested here.

    If you go with JTable for rendering scalability,

    1. This is no abuse; it is exactly how TableModel is intended to be used. TableModel models a rectangular matrix of whatever you decide. JTable is just an (efficiently rendered) view of that model.

    2. I prefer AbstractTableModel, shown here, because Vector is rarely the desired data structure. Use whatever container makes your indexing most convenient. DefaultTableModel is handy and serves as a guide to extending AbstractTableModel. In particular, you'll need a setValueAt().

      @Override
      public void setValueAt(Object aValue, int row, int col) {
          ... // update your data structure
          this.fireTableCellUpdated(row, col); // notify the view
      }
      
    0 讨论(0)
  • 2020-12-12 00:41

    longer comment, everything depends

    1) if is possible for Columns

    • resize

    • reordering

    2) if is possible for Columns

    • filtering

    • sorting

    a. then you have look at two JTables, first JTable only with TableHeader, simple with removed rows and second full sized JTable with TableHeader and Columns and rows,

    b. for interactions betweens two JTableHeader is there
    TableColumnModelListener#columnMarginChanged(ChangeEvent e) and columnMoved(TableColumnModelEvent e)

    c. everyting put to one JPanel inside JScrollPane

    d. if you'll change numbers of rows or colums (or filtering / sorting) then you have to notified JPanel for rezize JTable#getPreferredScrollableViewportSize() + Dimension for ontop JTable only with TableHeader

    very similair way as there (is everything that you needed)

    enter image description hereenter image description hereenter image description here

    (endless kudos for Rob)

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.table.*;
    
    public class TableFilterRow extends JFrame implements TableColumnModelListener {
        private static final long serialVersionUID = 1L;
    
        private JTable table;
        private JPanel filterRow;
    
        public TableFilterRow() {
            table = new JTable(3, 5);
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            JScrollPane scrollPane = new JScrollPane(table);
            getContentPane().add(scrollPane);
            table.getColumnModel().addColumnModelListener(this);
            //  Panel for text fields
            filterRow = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
            for (int i = 0; i < table.getColumnCount(); i++) {
                filterRow.add(new JTextField(" Sum at - " + i));
            }
            columnMarginChanged(new ChangeEvent(table.getColumnModel()));
            getContentPane().add(filterRow, BorderLayout.SOUTH);
        }
    
        //  Implement TableColumnModelListener methods
        //  (Note: instead of implementing a listener you should be able to
        //  override the columnMarginChanged and columMoved methods of JTable)
        @Override
        public void columnMarginChanged(ChangeEvent e) {
            TableColumnModel tcm = table.getColumnModel();
            int columns = tcm.getColumnCount();
    
            for (int i = 0; i < columns; i++) {
                JTextField textField = (JTextField) filterRow.getComponent(i);
                Dimension d = textField.getPreferredSize();
                d.width = tcm.getColumn(i).getWidth();
                textField.setPreferredSize(d);
            }
    
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    filterRow.revalidate();
                }
            });
        }
    
        @Override
        public void columnMoved(TableColumnModelEvent e) {
            Component moved = filterRow.getComponent(e.getFromIndex());
            filterRow.remove(e.getFromIndex());
            filterRow.add(moved, e.getToIndex());
            filterRow.validate();
        }
    
        @Override
        public void columnAdded(TableColumnModelEvent e) {
        }
    
        @Override
        public void columnRemoved(TableColumnModelEvent e) {
        }
    
        @Override
        public void columnSelectionChanged(ListSelectionEvent e) {
        }
    
        public static void main(String[] args) {
            JFrame frame = new TableFilterRow();
            frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    

    3) otherwise look How to Use Raised Borders in the prepareRederer

    4) this question has nothing to do with type of TableModel

    0 讨论(0)
提交回复
热议问题