Установите ширину столбца JTable в соответствии с текстом в заголовке

Мне нужно получить соответствующий размер таблицы в соответствии с текстом в заголовке. Он содержит сокращения чешских названий дней, таких как: "Po "," Út ","St»атс но вместо этого отображаются три точки.

У меня есть этот код :,

widthheight - максимум всех минимальных размеров строк / столбцов,

allWidthallHeight - должна быть общая ширина, высота всей таблицы I '

//GET DIMENSION
int width = 0;
int height = 0;
int allWidth, allHeight;
for (int col = 0; col < table.getColumnCount(); col++) {        
    TableColumn tableColumn = table.getTableHeader().getColumnModel().getColumn(col);
    TableCellRenderer renderer = tableColumn.getHeaderRenderer();
    if (renderer == null) {
        renderer = table.getTableHeader().getDefaultRenderer();
    }
    Component component = renderer.getTableCellRendererComponent(table,
            tableColumn.getHeaderValue(), false, false, -1, col);
    width = Math.max(component.getPreferredSize().width, width);
    table.getColumnModel().getColumn(col).setPreferredWidth(width);
}
allWidth = table.getColumnCount() * width;
for (int row = 0; row < table.getRowCount(); row++) {
    TableCellRenderer renderer = table.getCellRenderer(row, 0);
    Component comp = table.prepareRenderer(renderer, row, 0);
    height = Math.max(comp.getMinimumSize().height, height);
}
allHeight = table.getRowCount() * height;

//HERE I SET WIDTHS AND HEIGHTS
table.setRowHeight(height);
table.setMinimumSize(new Dimension(allWidth, allHeight));
scrollPane.setMinimumSize(new Dimension(allWidth, allHeight));

Я использую GridBagLayout с этими настройками, я думаю, что это нормально:

this.setBorder(BorderFactory.createTitledBorder("Calendar"));
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.gridy = 1;   //position x=0, y=0 is for JSpinners, months and years
gbc.weighty = 0;
gbc.weightx = 0;
add(scrollPane,gbc);//add table in a custom Calendar component

Кроме того, я изменил внешний вид, и это вызывает эти три точки. В противном случае имена отображаются правильно.

try {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
}

И вот как я инициализирую JTable и JScrollPane, у меня такое ощущение, что это тоже может быть хорошо.

    setTable(new JTable());
    getTable().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    getTable().setAutoscrolls(false);
    getTable().getTableHeader().setResizingAllowed(false);
    getTable().getTableHeader().setReorderingAllowed(false);
    getTable().setColumnSelectionAllowed(true);
    getTable().setRowSelectionAllowed(true);
    getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    tableModel = new CalendarTableModel();  //my class extended from AbstractTableModel
    getTable().setModel(tableModel);
    scrollPane = new JScrollPane(table,JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setAutoscrolls(false);

Проблемы:

Если я неЕсли установить scrollPane с помощью gbc, чтобы изменить его размер, он получит минимально возможный размер, если я не вычислю и не установлю минимальные размерыtable а такжеscrollPane рукой. (левая картинка)

Используя эти настройки, я получил результат в средней картинке, но тоже слишком маленький. (без названий дней и высота тоже несколько меньше.)

Я неЯ не знаю другого лучшего подхода для этого, ничего, что янашел, помог мне до сих пор.



Когда я рассмотрел некоторые отступы, например 2 пикселя, и скорректировал вычисление allWidth, allHeight, вот так:

allHeight = (1+table.getRowCount()+pady) * height; //plus one line of header
allWidth = table.getColumnCount() * width;

Я получил изображение справа.

  

Вот простой полный скомпилируемый класс, который демонстрирует проблему:

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

public class Main {
    public static void main(String[] args) {
        new Main().start();
    }

    private void start() {
        JFrame f = new JFrame();
        f.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        initTable();

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
        }

        JPanel calendar = new JPanel();
        calendar.setLayout(new GridBagLayout());
        calendar.setBorder(BorderFactory.createTitledBorder("Calendar"));
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weighty = 0;
        gbc.weightx = 0;
        calendar.add(scrollPane, gbc);

        f.add(calendar,gbc);

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    JTable table;
    JScrollPane scrollPane;
    CalendarTableModel tableModel;

    private void initTable() {
        setTable(new JTable());
        getTable().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        getTable().setAutoscrolls(false);
        getTable().getTableHeader().setResizingAllowed(false);
        getTable().getTableHeader().setReorderingAllowed(false);
        getTable().setColumnSelectionAllowed(true);
        getTable().setRowSelectionAllowed(true);
        getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        tableModel = new CalendarTableModel();  //my class extended from AbstractTableModel
        getTable().setModel(tableModel);
        scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setAutoscrolls(false);

        //GET DIMENSION
        int width = 0;
        int height = 0;
        int allWidth, allHeight;
        int padx = 2,pady = 2;
        for (int col = 0; col < table.getColumnCount(); col++) {
            TableColumn tableColumn = table.getTableHeader().getColumnModel().getColumn(col);
            TableCellRenderer renderer = tableColumn.getHeaderRenderer();
            if (renderer == null) {
                renderer = table.getTableHeader().getDefaultRenderer();
            }
            Component component = renderer.getTableCellRendererComponent(table,
                    tableColumn.getHeaderValue(), false, false, -1, col);
            width = Math.max(component.getPreferredSize().width, width);
            table.getColumnModel().getColumn(col).setPreferredWidth(width);
        }
        allWidth = (table.getColumnCount()+padx) * width;
        for (int row = 0; row < table.getRowCount(); row++) {
            TableCellRenderer renderer = table.getCellRenderer(row, 0);
            Component comp = table.prepareRenderer(renderer, row, 0);
            height = Math.max(comp.getMinimumSize().height, height);
        }
        allHeight = (1+table.getRowCount()+pady) * height;

//HERE I SET WIDTHS AND HEIGHTS
        table.setRowHeight(height);
        table.setMinimumSize(new Dimension(allWidth, allHeight));
        scrollPane.setMinimumSize(new Dimension(allWidth, allHeight));
    }

    private void setTable(JTable jTable) {
        this.table = jTable;
    }

    private JTable getTable() {
        return this.table;
    }

    private class CalendarTableModel extends AbstractTableModel {
        private String[] daysData = {"Po", "Út", "St", "Čt", "Pá", "So", "Ne"};
        private int[][] values;

        public CalendarTableModel() {
            values = new int[7][6];
            for (int i = 0; i < 6; i++) {
                for (int j = 0; j < 7; j++) {
                    values[j][i] = 7;
                }
            }
        }

        @Override
        public int getRowCount() {
            return 6;
        }

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

        @Override
        public String getColumnName(int column) {
            return daysData[column];
        }

        @Override
        public Object getValueAt(int row, int column) {
            return this.values[column][row];
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    }
}
 Daniel Katz22 авг. 2013 г., 13:59
Я работаю над этим.
 Daniel Katz22 авг. 2013 г., 14:16
@mKorbel Где я должен опубликовать это?
 mKorbel22 авг. 2013 г., 13:22
table.setPreferredScrollableViewportSize (table.getPreferredSize ());
 Daniel Katz22 авг. 2013 г., 13:18
Возможно, мне следует отредактировать вопрос, чтобы добавить еще одну картинку.
 kleopatra22 авг. 2013 г., 15:44
главная проблема в том, что вы путаете каждого соавтора с настройкой LAFпосле создание / настройка компонентов.
 Daniel Katz22 авг. 2013 г., 13:12
хорошо япопробую .. Я подумал, что это то, что я мог бы получить от какого-то метода.
 mKorbel22 авг. 2013 г., 13:25
Возможно, мне следует отредактировать вопрос, чтобы добавить еще одну картинку. Для лучшей помощи скорее опубликуйте SSCCE, краткую, запускаемую, компилируемую, примерно о JFrame с JTable в JScrollPane, и жестко запрограммированное значение для XxxTableModel, продемонстрированное в виде проблемы.
 Daniel Katz22 авг. 2013 г., 14:08
Я забыл упомянуть, что я изменил внешний вид. У меня уже есть скомпилированный код в одном простом классе.
 Daniel Katz22 авг. 2013 г., 14:53
@mKorbel I 'мы сделали это У меня есть половина решения, и любой может использовать его, чтобы ответить мне. Но я неЯ не понимаю, почему это так, что мне нужно изменить внешний вид, прежде чем создавать какой-либо кадр. Вы можете легко попытаться поставить изменение LAF в качестве первой команды. Это все еще нене помогите мне установить подходящий размер, потому что использование отступов, таких как 2 пикселя или 1, только обрезает таблицу или создает слишком большой 'немного' границы.
 mKorbel22 авг. 2013 г., 14:42
отредактируйте свой вопрос с помощью запускаемого, скомпилированного кода, содержащего основной класс
 mKorbel22 авг. 2013 г., 14:54
и хороший :-) "Я"
 MadProgrammer22 авг. 2013 г., 13:18
Вместо того, чтобы использовать setMin / pref size, взгляните на getPreferredScrollableViewportSize
 Andrew Thompson22 авг. 2013 г., 15:23
мы сделали это. "  Сделано что? Где SSCCE?
 Daniel Katz22 авг. 2013 г., 18:17
Извините, в моем проекте была похожая проблема, которую я неЯ понял, что мне пришлось оставить это не в том месте, чтобы проблема осталась. Если бы я нет, половина проблемы будет решена. Когда я опубликовал SSCCE, я указал на эту проблему.
 MadProgrammer22 авг. 2013 г., 13:10
Столбцы таблицы также имеют отступы, учитывающие линии сетки. Попробуйте добавить что-то вроде 2 или 4 в ваши расчеты ширины ...

Ответы на вопрос(3)

Я пришел к решению :-)

Мне пришлось изменить внешний вид, прежде чем я рассчитал соответствующие ширины столбцов. Когда я сделал это наоборот, расчет был устаревшим.

Так что мне нужно было только установить правильную ширину, как это:

table.getColumnModel().getColumn(col).setPreferredWidth(width);

А затем измените размер viewPort следующим образом, потому что таблица 's предпочтительный размер теперь правильный.

table.setPreferredScrollableViewportSize(table.getPreferredSize());

Спасибо! ;)

 Daniel Katz22 авг. 2013 г., 16:15
В моем приложении проблема осталась, хотя я сменил LAF перед расчетом. Я должен был вывести LAF из конструктора JFrame перед ним.
 kleopatra22 авг. 2013 г., 17:08
пришлось положить LAF из конструктора JFrame Похоже, вы расширяете JFrame - этонеправильно большую часть времени. Вместо,использование кадр, как вы делаете в своем SSCCE

Это фантастический код для автоматической подгонки вашего заголовка и содержимого ячейки в JTable:

jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF );

for (int column = 0; column < jTable1.getColumnCount(); column++){
    TableColumn tableColumn = jTable1.getColumnModel().getColumn(column);
    int preferredWidth = tableColumn.getMinWidth();
    int maxWidth = 0;
    TableCellRenderer rend = jTable1.getTableHeader().getDefaultRenderer();
    TableCellRenderer rendCol = tableColumn.getHeaderRenderer();
    if (rendCol == null) rendCol = rend;
    Component header = rendCol.getTableCellRendererComponent(jTable1, tableColumn.getHeaderValue(), false, false, 0, column);
    maxWidth = header.getPreferredSize().width;
    System.out.println("maxWidth :"+maxWidth);

    for (int row = 0; row < jTable1.getRowCount(); row++){
        TableCellRenderer cellRenderer = jTable1.getCellRenderer(row, column);
        Component c = jTable1.prepareRenderer(cellRenderer, row, column);
        int width = c.getPreferredSize().width + jTable1.getIntercellSpacing().width;
        preferredWidth = Math.max(preferredWidth, width);
        System.out.println("preferredWidth :"+preferredWidth);
        System.out.println("Width :"+width);

        //  We've exceeded the maximum width, no need to check other rows

        if (preferredWidth 
Решение Вопроса

Вы можете получить это

от

f.pack() доf.setVisible(true);

желаемый вид должен быть в 22/23 пикселей, ноcomponent.getPreferredSize() или жеSwingUtilities#computeStringWidth(FontMetrics fm, String str) возвращает только 17/18 и плюсtable.getIntercellSpacing().width только один пиксель для Po - Ne

обратите внимание, что реальный обход может быть основан наTableColumnAdjuster от @camickr

из кода

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

public class Main {

    public static void main(String[] args) {
        new Main().start();
    }

    private void start() {
        JFrame f = new JFrame();
        f.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        initTable();

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
        }

        JPanel calendar = new JPanel();
        calendar.setLayout(new GridBagLayout());
        calendar.setBorder(BorderFactory.createTitledBorder("Calendar"));
        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weighty = 0;
        gbc.weightx = 0;
        calendar.add(scrollPane, gbc);
        f.add(calendar, gbc);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);
    }
    JTable table;
    JScrollPane scrollPane;
    CalendarTableModel tableModel;

    private void initTable() {
        setTable(new JTable());
        getTable().setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        getTable().setAutoscrolls(false);
        getTable().getTableHeader().setResizingAllowed(false);
        getTable().getTableHeader().setReorderingAllowed(false);
        getTable().setColumnSelectionAllowed(true);
        getTable().setRowSelectionAllowed(true);
        getTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        tableModel = new CalendarTableModel();  //my class extended from AbstractTableModel
        getTable().setModel(tableModel);
        scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setAutoscrolls(false);

        TableColumnModel columnModel = table.getColumnModel();
        for (int col = 0; col < table.getColumnCount(); col++) {
            int maxWidth = 0;
            for (int row = 0; row < table.getRowCount(); row++) {
                TableCellRenderer rend = table.getCellRenderer(row, col);
                Object value = table.getValueAt(row, col);
                Component comp = rend.getTableCellRendererComponent(table, value, false, false, row, col);
                maxWidth = Math.max(comp.getPreferredSize().width, maxWidth);
            }
            TableColumn column = columnModel.getColumn(col);
            TableCellRenderer headerRenderer = column.getHeaderRenderer();
            if (headerRenderer == null) {
                headerRenderer = table.getTableHeader().getDefaultRenderer();
            }
            Object headerValue = column.getHeaderValue();
            Component headerComp = headerRenderer.getTableCellRendererComponent(table, headerValue, false, false, 0, col);
            maxWidth = Math.max(maxWidth, headerComp.getPreferredSize().width);
            // note some extra padding
            column.setPreferredWidth(maxWidth + 6);//IntercellSpacing * 2 + 2 * 2 pixel instead of taking this value from Borders
        }
        DefaultTableCellRenderer stringRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class);
        stringRenderer.setHorizontalAlignment(SwingConstants.CENTER);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
    }

    private void setTable(JTable jTable) {
        this.table = jTable;
    }

    private JTable getTable() {
        return this.table;
    }

    private class CalendarTableModel extends AbstractTableModel {

        private String[] daysData = {"Pondelok", "Út", "St", "Čt", "Pá", "Sobota", "Ne"};
        private int[][] values;

        public CalendarTableModel() {
            values = new int[7][6];
            for (int i = 0; i < 6; i++) {
                for (int j = 0; j < 7; j++) {
                    values[j][i] = 30;
                }
            }
        }

        @Override
        public int getRowCount() {
            return 6;
        }

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

        @Override
        public String getColumnName(int column) {
            return daysData[column];
        }

        @Override
        public Object getValueAt(int row, int column) {
            return this.values[column][row];
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    }
}

Ваш ответ на вопрос