Skip to content

Latest commit

 

History

History
126 lines (99 loc) · 8.92 KB

File metadata and controls

126 lines (99 loc) · 8.92 KB

Overview

  1. Notes on JTable
  2. JTable has a lot of legacy baggage
  3. Probably simpler to use SpringLayout or GroupLayout or MigLayout to build a "Table"
    1. Resizing might be tough
  4. Still a good idea to separate model afrom presentation
  1. Does not store its own data, uses TableModel (see below)
  2. Supports sorting & filtering via RowSorter
  3. Supports headers
  4. Supports column resizing
  5. Supports custom header rendering
  6. Supports custom cell rendering
  7. Supports editing values in cells
  8. JTable address rows and columns only by int, zero based
  9. Column rearranging does NOT affect the model
  10. Layout: https://docs.oracle.com/en/java/javase/20/docs/api/java.desktop/javax/swing/JTable.html#doLayout()
    1. Columns resize to respond to change in containing parent
  11. When you put JTable into a JScrollPane, the header stays on top
    1. If you don’t wrap the JTable in a JScrollPane, you must explicitly add the header
  12. Managing rows is very different from managing columns
  13. GOTCHA: JButton doesn't work in a JTable row
  14. GOTCHA: Hard to control spacing
  15. GOTCHA: Layout is overly complex and not so useful
  16. GOTCHA: Cells cannot contain arbitrary components (eg. no JButton)

Relationships

  1. JTable -> TableColumnModel -> TableColumn -> TableCellRenderer
  2. JTable -> TableModel

Rows

  1. Resizing: setRowHeight(...) and row specific version
  2. Space between rows: setRowMargin(margin)

Columns

  1. Resizing
    1. See setAutoResizeMode(...)
      1. AUTO_RESIZE_SUBSEQUENT_COLUMNS: (default) Resize all subsequent columns equally, preserve total width
      2. AUTO_RESIZE_OFF: Don’t resize columns; change the table width when parent size changes
      3. ... other options aren't as useful
  2. Space between columns
    1. TODO ...

Width: JTable adjusts its own width to fit into container

  1. See AUTO_RESIZE_OFF
  2. GOTCHA: You cannot set just one column width, you must set all getColumnModel().getColumn(i).setPreferredWidth(...)
  3. GOTCHA: col.setWidth does NOT work
    public static void setColumnWidths(
            JTable table,
            int totalTableWidth,
            int... percentages) {

        Objects.requireNonNull(table, "table is required and null.");
        Objects.requireNonNull(percentages, "percentages is required and null.");
        checkArgument(totalTableWidth > 0, "totalTableWidth must be positive > 0");
        checkArgument(percentages.length == table.getColumnCount(),
                "percentages must have the same length as the table columns");
        Arrays.stream(percentages).forEach(p -> {
            checkArgument(p >= 0, "percentages must be positive > 0");
            checkArgument(p <= 100, "percentages must be <= 100");
        });

        final var pctSum = Arrays.stream(percentages).sum();

        for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) {
            var w = (percentages[i] / pctSum) * totalTableWidth;
            table.getColumnModel()
                    .getColumn(i)
                    .setPreferredWidth(w);
        }
    }

Idioms

  1. Put the JTable into a JScrollPane
  2. DON'T set preferred size on JTable, set table.setFillsViewportHeight(true);
  3. You can display the Header separately from the Body (see getTableHeader()
    1. JScrollPane does this automatically
  1. Extend AbstractTableModel, using a java.util.List of your own row type
  2. Manages contents/data/values in each cell
  3. NOT for presentation, just data
  4. Use Lock for synchronization
  5. Don't use DefaultTableModel because it uses Vector and does some unnecessary lookups
  6. Your model should be mutable (to avoid reconnecting the model to Table & Sorter repeatedly)
    1. Allow replacement, adding, clearing of Collection<YourRowType>
    2. fireTableDataChanged(); after changing data
      1. GOTCHA: fireTableStructureChanged(); replaces TableColumns and TableCellRenderers
  7. Column rearranging does NOT affect the model
    1. Only a view/presentation trick
    2. No need to listen for column reorder events
  8. RowSorter sorting & filtering does NOT affect the model
  1. Manages column count, total width, selectability, etc
  2. Useful for dynamically adding/removing columns
  3. TableColumns belong to the ColumnModel (not the JTable)
  4. Column gaps defined here
  1. Maps between "coordinates" of rows in the model and rows in the UI
  2. to programmatically sort (eg. default sort on init), call sort()
  3. Apply sorter to table via table.setRowSorter(...)
  4. Row Selection uses the visible index, so convert using convertRowIndexToView(...) or convertRowIndexToModel(...)

Cell Renderer

  1. TODO: more here

Other Resources

  1. Official usage guide