简体   繁体   English

如何自动将JTable的所有列调整为相同大小?

[英]How to auto-resize all columns of a JTable to the same size?

I'm using a JTable on a project. 我在项目上使用JTable。 I want the table to auto-resize all columns to the same size, and at the same time, to fill the width of the containing JScrollPane. 我希望表格将所有列自动调整为相同大小,并同时填充包含JScrollPane的宽度。

I can't just set a preferred width to a fixed value, because when the user will resize the frame, I want all the columns being resized to the same size, but with the constraint that it must still fill 100% of the JScrollPane. 我不能只是将首选宽度设置为固定值,因为当用户调整框架的大小时,我希望所有列都被调整为相同的大小,但有一个约束,即它仍必须填充100%的JScrollPane。

For instance, if the JScrollPane has a width of 1000, and I've got 10 columns, I'd like the columns to each have a size of 100. If the JScrollPane is then shrinked to 500, I'd like the columns to resize to 50 each. 例如,如果JScrollPane的宽度为1000,并且我有10列,我希望这些列的大小为100。如果JScrollPane然后缩小到500,我希望这些列调整为每个50。

For now, I just set JTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF) and here's the result : 现在,我只设置JTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF) ,结果如下:

在此处输入图片说明

How can I simply achieve that ? 我怎样才能做到这一点?

Thanks. 谢谢。

You need some way to update the column model when the table changes size. 当表更改大小时,您需要某种方法来更新列模型。

This basic example uses the invaldiate method to update it's column model. 这个基本示例使用invaldiate方法更新其列模型。 It also sets the columns as "not" resizable. 它还将列设置为“不可”调整大小。

This also overrides the tables getScrollableTracksViewportWidth method to ensure that the table automatically fills the horizontal space. 这还将覆盖表的getScrollableTracksViewportWidth方法,以确保表自动填充水平空间。 This does mean that it will never display a horizontal scroll bar though. 这确实意味着它永远不会显示水平滚动条。

public class SpringTable extends JTable {

    public SpringTable(TableModel dm) {
        super(dm);
        setAutoResizeMode(AUTO_RESIZE_OFF);
    }

    public SpringTable() {
        setAutoResizeMode(AUTO_RESIZE_OFF);
    }

    @Override
    public void doLayout() {
        int width = getWidth();
        int columnCount = getColumnCount();
        int columnSize = width / columnCount;
        for (int index = 0; index < columnCount; index++) {
            TableColumn column = getColumnModel().getColumn(index);
            column.setResizable(false);
            column.setPreferredWidth(width);
        }
        super.doLayout();
    }

    @Override
    public boolean getScrollableTracksViewportWidth() {
        return true;
    }

}

It may be better to use doLayout instead on invalidate , but you should have a play and see what meets your needs 最好在invalidate上使用doLayout代替,但是您应该进行一下测试,看看能满足您的需求

Running example 运行示例

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

public class TestJTable {

    public static void main(String[] args) {
        new TestJTable();
    }

    public TestJTable() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                List<Pet> pets = new ArrayList<>(25);
                pets.add(new Pet("Tyrannosauridae", "TYRANNOSAURUS", 20, 35));
                pets.add(new Pet("Dromaeosauridae", "VELOCIRAPTOR", 45, 90));
                pets.add(new Pet("Ceratopsidae", "TRICERATOPS", 15, 30));
                pets.add(new Pet("Stegosauridae", "STEGOSAURUS", 22, 25));
                pets.add(new Pet("Titanosauridae", "MALAWISAURUS", 22, 25));
                pets.add(new Pet("Compsognathidae", "COMPSOGNATHUS", 8, 25));
                pets.add(new Pet("Brachiosauridae", "BRACHIOSAURUS", 8, 25));
                pets.add(new Pet("Diplodocidae", "DIPLODOCUS", 8, 25));

                final PetTableModel model = new PetTableModel(pets);
                final JTable table = new SpringTable(model);

                InputMap im = table.getInputMap(JTable.WHEN_FOCUSED);
                ActionMap am = table.getActionMap();
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "delete");
                am.put("delete", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        int[] indicies = table.getSelectedRows();
                        int[] mapped = new int[indicies.length];
                        for (int index = 0; index < indicies.length; index++) {
                            mapped[index] = table.convertRowIndexToModel(indicies[index]);
                        }
                        model.removePets(mapped);
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class SpringTable extends JTable {

        public SpringTable(TableModel dm) {
            super(dm);
            setAutoResizeMode(AUTO_RESIZE_OFF);
        }

        public SpringTable() {
            setAutoResizeMode(AUTO_RESIZE_OFF);
        }

        @Override
        public void doLayout() {
            int width = getWidth();
            int columnCount = getColumnCount();
            int columnSize = width / columnCount;
            for (int index = 0; index < columnCount; index++) {
                TableColumn column = getColumnModel().getColumn(index);
                column.setResizable(false);
                column.setPreferredWidth(width);
            }
            super.doLayout();
        }

        @Override
        public boolean getScrollableTracksViewportWidth() {
            return true;
        }

    }

    public class PetTableModel extends AbstractTableModel {

        private List<Pet> pets;

        public PetTableModel() {
            pets = new ArrayList<>(25);
        }

        public PetTableModel(List<Pet> pets) {
            this.pets = pets;
        }

        @Override
        public int getRowCount() {
            return pets.size();
        }

        public void removePets(int... indicies) {
            List<Pet> old = new ArrayList<>(indicies.length);
            for (int index : indicies) {
                old.add(pets.get(index));
            }

            for (Pet pet : old) {
                int index = pets.indexOf(pet);
                pets.remove(pet);
                fireTableRowsDeleted(index, index);
            }
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            Class clazz = String.class;
            switch (columnIndex) {
                case 2:
                case 3:
                    clazz = Float.class;
            }
            return clazz;
        }

        @Override
        public String getColumnName(int column) {
            String name = "??";
            switch (column) {
                case 0:
                    name = "Breed";
                    break;
                case 1:
                    name = "Category";
                    break;
                case 2:
                    name = "Buy Price";
                    break;
                case 3:
                    name = "Sell Price";
                    break;
            }
            return name;
        }

        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Pet pet = pets.get(rowIndex);
            Object value = null;
            switch (columnIndex) {
                case 0:
                    value = pet.getBreed();
                    break;
                case 1:
                    value = pet.getCategory();
                    break;
                case 2:
                    value = pet.getBuyPrice();
                    break;
                case 3:
                    value = pet.getSellPrice();
                    break;
            }
            return value;
        }

        public void add(Pet pet) {
            pets.add(pet);
            fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
        }

    }

    public class Pet {

        private String breed;
        private String category; 
        private float buyPrice; 
        private float sellPrice; 

        public Pet(String breed, String category, float buyPrice, float sellPrice) {
            this.breed = breed;
            this.category = category;
            this.buyPrice = buyPrice;
            this.sellPrice = sellPrice;
        }

        public String getBreed() {
            return breed;
        }

        public float getBuyPrice() {
            return buyPrice;
        }

        public String getCategory() {
            return category;
        }

        public float getSellPrice() {
            return sellPrice;
        }

    }

}

As best as I can tell the default behaviour (using JDK7 on Windows 7) of a JTable is to equally size each column when the table size is changed. 尽我所知,更改表大小后,JTable的默认行为(在Windows 7上使用JDK7)是将各列的大小均等。 This seems to work as long as you haven't set a preferred width on the table column. 只要您没有在表格列上设置首选宽度,这似乎就可以工作。

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

public class TestJTable {

    public static void main(String[] args) {
        new TestJTable();
    }

    public TestJTable() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }


                String[] columnNames = {"Column1", "a", "a long long column name", "column4"};
                DefaultTableModel model = new DefaultTableModel(columnNames, 5);
                final JTable table = new JTable(model);

                JButton button = new JButton("Display Column Widths");
                button.addActionListener( new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        int columnCount = table.getColumnCount();

                        for (int index = 0; index < columnCount; index++)
                        {
                            TableColumn column = table.getColumnModel().getColumn(index);
                            System.out.print(column.getWidth() + ", ");
                        }

                        System.out.println();
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.add(button, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

调整JTable中后,就可以得到新的宽度(JTable.getWidth()),除以10(作出必要的调整,以获得一个整数结果),然后手动设置每列的宽度(看看这个帮助)。

I used this in my last project! 我在上一个项目中使用了它!

addComponentListener(new ComponentListener() {
    @Override public void componentShown(ComponentEvent e) {}
    @Override public void componentMoved(ComponentEvent e) {}           
    @Override public void componentHidden(ComponentEvent e) {}

    @Override
    public void componentResized(ComponentEvent e) {
        int w = table.getWidth() / table.getColumnCount();
        for(int i = 0; i < table.getColumnCount(); i++) {
            table.getColumn(i).setPreferredWidth(w);
        }
    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM