How to adjust JTable columns to fit the longest content in column cells

后端 未结 2 1275
野性不改
野性不改 2020-12-01 10:15

I\'m using answer https://stackoverflow.com/a/5820366 and http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/ and it works, but frequently columns\' sizes are t

相关标签:
2条回答
  • 2020-12-01 10:18

    Seems to be working okay for me...

    enter image description here

    public class TestTable01 extends JPanel {
    
        private JTable mainTable;
    
        public TestTable01() {
            super(new GridLayout(1, 0));
    
            String[] columnNames = {"First Name",
                                    "Last Name",
                                    "Sport",
                                    "# of Years",
                                    "Vegetarian"};
    
            Object[][] data = {
                {"Kathy", "Smith",
                 "Snowboarding", new Integer(5), new Boolean(false)},
                {"John", "Doe",
                 "Rowing", new Integer(3), new Boolean(true)},
                {"Sue", "Black",
                 "Knitting", new Integer(2), new Boolean(false)},
                {"Jane", "White",
                 "Speed reading", new Integer(20), new Boolean(true)},
                {"Joe", "Brown",
                 "Pool", new Integer(10), new Boolean(false)}
            };
    
            mainTable = new JTable(data, columnNames);
            mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            mainTable.setPreferredScrollableViewportSize(new Dimension(500, 70));
            mainTable.setFillsViewportHeight(true);
    
            update();
    
            //Create the scroll pane and add the table to it.
            JScrollPane scrollPane = new JScrollPane(mainTable);
    
            //Add the scroll pane to this panel.
            add(scrollPane);
        }
    
        /**
         * Create the GUI and show it. For thread safety, this method should be
         * invoked from the event-dispatching thread.
         */
        private static void createAndShowGUI() {
            //Create and set up the window.
            JFrame frame = new JFrame("SimpleTableDemo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            //Create and set up the content pane.
            TestTable01 newContentPane = new TestTable01();
            newContentPane.setOpaque(true); //content panes must be opaque
            frame.setContentPane(newContentPane);
    
            //Display the window.
            frame.pack();
            frame.setVisible(true);
        }
    
        private void update() {
            System.out.println("updating");
    
            adjustJTableRowSizes(mainTable);
            for (int i = 0; i < mainTable.getColumnCount(); i++) {
                adjustColumnSizes(mainTable, i, 2);
            }
        }
    
        private void adjustJTableRowSizes(JTable jTable) {
            for (int row = 0; row < jTable.getRowCount(); row++) {
                int maxHeight = 0;
                for (int column = 0; column < jTable.getColumnCount(); column++) {
                    TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column);
                    Object valueAt = jTable.getValueAt(row, column);
                    Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column);
                    int heightPreferable = tableCellRendererComponent.getPreferredSize().height;
                    maxHeight = Math.max(heightPreferable, maxHeight);
                }
                jTable.setRowHeight(row, maxHeight);
            }
    
        }
    
        public void adjustColumnSizes(JTable table, int column, int margin) {
            DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
            TableColumn col = colModel.getColumn(column);
            int width;
    
            TableCellRenderer renderer = col.getHeaderRenderer();
            if (renderer == null) {
                renderer = table.getTableHeader().getDefaultRenderer();
            }
            Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0);
            width = comp.getPreferredSize().width;
    
            for (int r = 0; r < table.getRowCount(); r++) {
                renderer = table.getCellRenderer(r, column);
                comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, column), false, false, r, column);
                int currentWidth = comp.getPreferredSize().width;
                width = Math.max(width, currentWidth);
            }
    
            width += 2 * margin;
    
            col.setPreferredWidth(width);
            col.setWidth(width);
        }
    
        public static void main(String[] args) {
            //Schedule a job for the event-dispatching thread:
            //creating and showing this application's GUI.
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
    
            });
        }
    
    }
    

    UPDATED

    There are a number of issues with your example.

    • Tables really should be added to a JScrollPane, this will take care of adding the header...
    • The default layout manager for a JPanel is FlowLayout, in this case, it's probably not what you want, you probably want to use a BorderLayout
    • Swing is not thread safe. The user of java.util.Timer will violate this policy, this could cause the model and view to fall out sync. Use a javax.swing.Timer instead.
    • Rendering two <div> next to each will cause the html layout engine to place a weak break between the elements. That is, if the engine decides there's not enough available space to render the two elements together, it will split them. Better to use a single <div> with two <span> tags instead...

    I would have a read of

    • Concurrency in Swing
    • How to Use Tables

    enter image description here

    public class TestColumnWidths {
    
        private static JTable mainTable;
        private static Random random = new Random();
        private static List<Data> data;
    
        private static class Data {
    
            String name;
            String surname;
    
            private Data(String name, String surname) {
                this.name = name;
                this.surname = surname;
            }
        }
    
        public static void main(String[] args) {
    
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
    
                    data = stubProvider();
    
                    final JFrame frame = new JFrame("table adjust example");
                    frame.add(createUI());
                    frame.pack();
                    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    update();
    //                    java.util.Timer timer = new java.util.Timer();
    //                    timer.schedule(new TimerTask() {
    //                        @Override
    //                        public void run() {
    //                            update();
    //                        }
    //                    }, 3000, 3000);
    
                    javax.swing.Timer timer = new javax.swing.Timer(3000, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            update();
                        }
                    });
                    timer.setRepeats(true);
                    timer.setCoalesce(true);
                    timer.start();
    
                }
            });
        }
    
        private static JPanel createUI() {
            JPanel jPanel = new JPanel();
            mainTable = new JTable(2, 3);
            mainTable.setModel(new AbstractTableModel() {
                @Override
                public int getRowCount() {
                    return data.size();
                }
    
                @Override
                public int getColumnCount() {
                    return 2;
                }
    
                @Override
                public Object getValueAt(int rowIndex, int columnIndex) {
                    Data dataItem = data.get(rowIndex);
                    if (columnIndex == 0) {
                        return dataItem.name;
                    }
                    if (columnIndex == 1) {
                        return dataItem.surname;
                    }
                    throw new IllegalStateException();
                }
            });
            mainTable.setGridColor(Color.black);
            mainTable.setShowHorizontalLines(false);
            mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    
            final TableCellRenderer defaultRenderer = mainTable.getTableHeader().getDefaultRenderer();
            mainTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
                @Override
                public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int row, int column) {
                    JLabel parent = (JLabel) defaultRenderer.getTableCellRendererComponent(jTable, o, b, b1, row, column);
                    if (column == 0) {
                        parent.setText("name");
                    } else {
                        parent.setText("surname");
                    }
                    return parent;
                }
            });
    
    //            jPanel.add(mainTable.getTableHeader());
    //            jPanel.add(mainTable);
    
            jPanel.setLayout(new BorderLayout());
            jPanel.add(new JScrollPane(mainTable));
    
            return jPanel;
        }
    
        private static void update() {
            System.out.println("updating");
            data = stubProvider();
    
            adjustJTableRowSizes(mainTable);
            for (int i = 0; i < mainTable.getColumnCount(); i++) {
                adjustColumnSizes(mainTable, i, 2);
            }
        }
    
        private static void adjustJTableRowSizes(JTable jTable) {
            for (int row = 0; row < jTable.getRowCount(); row++) {
                int maxHeight = 0;
                for (int column = 0; column < jTable.getColumnCount(); column++) {
                    TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column);
                    Object valueAt = jTable.getValueAt(row, column);
                    Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column);
                    int heightPreferable = tableCellRendererComponent.getPreferredSize().height;
                    maxHeight = Math.max(heightPreferable, maxHeight);
                }
                jTable.setRowHeight(row, maxHeight);
            }
    
        }
    
        public static void adjustColumnSizes(JTable table, int column, int margin) {
            DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
            TableColumn col = colModel.getColumn(column);
            int width;
    
            TableCellRenderer renderer = col.getHeaderRenderer();
            if (renderer == null) {
                renderer = table.getTableHeader().getDefaultRenderer();
            }
            Component comp = renderer.getTableCellRendererComponent(
                    table, col.getHeaderValue(), false, false, 0, 0);
            width = comp.getPreferredSize().width;
    
            for (int r = 0; r < table.getRowCount(); r++) {
                renderer = table.getCellRenderer(r, column);
                comp = renderer.getTableCellRendererComponent(
                        table, table.getValueAt(r, column), false, false, r, column);
                int currentWidth = comp.getPreferredSize().width;
                width = Math.max(width, currentWidth);
            }
    
            width += 2 * margin;
    
            col.setPreferredWidth(width);
        }
    
        private static List<Data> stubProvider() {
            List<Data> data = new ArrayList<Data>();
            for (int i = 0; i < 4; i++) {
                data.add(new Data(
                        "<html>"
                        + "<div>"
                        + "<span style='font-size: 15px'>Jason</span>"
                        + "<span style='font-size: 15px'>" + random.nextInt() + "</span>"
                        + "</div>"
                        + "</html>",
                        "Statham " + random.nextInt()));
            }
            return data;
        }
    }
    
    0 讨论(0)
  • 2020-12-01 10:25

    Set reasonable MinimumWidth for the columns which are too narrow. Then calculate width according to the contents of the columns and set them.

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