【问题标题】:JTable not honoring cell renderer's necessary heightJTable 不遵守单元格渲染器的必要高度
【发布时间】:2018-05-29 10:06:31
【问题描述】:

这应该很简单,但我不知道出了什么问题。我需要我的表格以相当大的字体大小显示,但表格画家不尊重单元格渲染器的高度。

我见过this post,当我的首选项窗口的字体大小发生变化时,它的效果非常好。但是尽管渲染器知道要使用什么字体大小,初始显示的表格使用的是标准行高 (16)。当然,桌面画家应该自动考虑渲染器的首选高度吗?还是我实际上必须手动告诉它要使用什么高度?

如下所示,我尝试调用doLayout(),但没有任何区别。

这里有一个 SSCCE 来演示这个问题:

public class IncorrectRowHeight extends JPanel
{
    private class MyCellRenderer extends JTextField implements TableCellRenderer
    {
        private MyCellRenderer()
        {
            setFont(new Font("SansSerif", Font.PLAIN, 30));
            setBorder(BorderFactory.createEmptyBorder());
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                                                       int row, int column)
        {
            setText(value.toString());
            return this;
        }
    }

    public IncorrectRowHeight()
    {
        super(new BorderLayout());

        add(new JTextField(25), BorderLayout.PAGE_START);

        String[][] data = {
                {"a", "b", "c", "d", "e"},
                {"f", "g", "h", "i", "j"},
                {"k", "l", "m", "n", "o"},
                {"p", "q", "r", "s", "t"}
        };
        String[] cols = {"h1", "h2", "h3", "h4", "h5"};
        JTable t = new JTable(data, cols);
        t.setGridColor(Color.GRAY);
        t.setPreferredScrollableViewportSize(new Dimension(300, 65));
        TableColumnModel model = t.getColumnModel();
        for (int i = 0; i < model.getColumnCount(); i++)
        {
            TableColumn column = model.getColumn(i);
            column.setCellRenderer(new MyCellRenderer());
        }
        JScrollPane scroller = new JScrollPane(t);
        add(scroller, BorderLayout.CENTER);

        //t.doLayout();  // doesn't help matters
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("IncorrectRowHeight");
        JComponent newContentPane = new IncorrectRowHeight();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

它产生以下内容:

这不是火箭科学!我做错了什么?

【问题讨论】:

  • JTable 使用rowHeight 属性来确定行的高度。您可以考虑使用它来尝试估计行的最佳高度
  • 所以,换句话说,我需要告诉 JTable 使用什么高度,它不可能足够聪明地从单元格渲染器中找出来???

标签: java swing tablecellrenderer


【解决方案1】:

使用 table.setRowHeight(table.getFontMetrics(font).getHeight());

package com.logicbig.example;

import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;

public class IncorrectRowHeight extends JPanel {
private static final Font font = new Font("SansSerif", Font.PLAIN, 30);
private class MyCellRenderer extends JTextField implements TableCellRenderer {
    private MyCellRenderer() {
        setFont(font);
        setBorder(BorderFactory.createEmptyBorder());
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                                                   int row, int column) {
        setText(value.toString());
        return this;
    }
}

public IncorrectRowHeight() {
    super(new BorderLayout());

    add(new JTextField(25), BorderLayout.PAGE_START);

    String[][] data = {
            {"a", "b", "c", "d", "e"},
            {"f", "g", "h", "i", "j"},
            {"k", "l", "m", "n", "o"},
            {"p", "q", "r", "s", "t"}
    };
    String[] cols = {"h1", "h2", "h3", "h4", "h5"};
    JTable t = new JTable(data, cols);
    t.setRowHeight(t.getFontMetrics(font).getHeight());
    t.setGridColor(Color.GRAY);
    t.setPreferredScrollableViewportSize(new Dimension(300, 65));
    TableColumnModel model = t.getColumnModel();
    for (int i = 0; i < model.getColumnCount(); i++) {
        TableColumn column = model.getColumn(i);
        column.setCellRenderer(new MyCellRenderer());
    }
    JScrollPane scroller = new JScrollPane(t);
    add(scroller, BorderLayout.CENTER);

    //t.doLayout();  // doesn't help matters
}

private static void createAndShowGUI() {
    JFrame frame = new JFrame("IncorrectRowHeight");
    JComponent newContentPane = new IncorrectRowHeight();
    newContentPane.setOpaque(true);
    frame.setContentPane(newContentPane);
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
  }
 }

【讨论】:

  • 我真的很喜欢getFontMetrics()的使用,感谢指点
【解决方案2】:

这个方法可能对你有帮助

public static void updateRowHeight(JTable table, int margin) {
    final int rowCount = table.getRowCount();
    final int colCount = table.getColumnCount();
    for (int i = 0; i < rowCount; i++) {
        int maxHeight = 0;
        for (int j = 0; j < colCount; j++) {
            final TableCellRenderer renderer = table.getCellRenderer(i, j);
            maxHeight = Math.max(maxHeight, table.prepareRenderer(renderer, i, j).getPreferredSize().height);
        }
        table.setRowHeight(i, maxHeight + margin);
    }
}

在表格填充数据后使用此方法。 margin 参数用于额外增加行高。如果不需要 - 使用 0。

这是您的示例,具有正确的单元格高度。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * <code>IncorrectRowHeight</code>.
 */
public class IncorrectRowHeight extends JPanel {
    private class MyCellRenderer extends JTextField implements TableCellRenderer {
        private MyCellRenderer() {
            setFont(new Font("SansSerif", Font.PLAIN, 30));
            setBorder(BorderFactory.createEmptyBorder());
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            setText(value.toString());
            return this;
        }
    }

    public IncorrectRowHeight() {
        super(new BorderLayout());

        add(new JTextField(25), BorderLayout.PAGE_START);

        String[][] data = {{"a", "b", "c", "d", "e"}, {"f", "g", "h", "i", "j"}, {"k", "l", "m", "n", "o"}, {"p", "q", "r", "s", "t"}};
        String[] cols = {"h1", "h2", "h3", "h4", "h5"};
        JTable t = new JTable(data, cols);
        t.setGridColor(Color.GRAY);
        t.setPreferredScrollableViewportSize(new Dimension(300, 65));
        TableColumnModel model = t.getColumnModel();
        for (int i = 0; i < model.getColumnCount(); i++) {
            TableColumn column = model.getColumn(i);
            column.setCellRenderer(new MyCellRenderer());
        }
        updateRowHeight(t, 0);
        JScrollPane scroller = new JScrollPane(t);
        add(scroller, BorderLayout.CENTER);
    }

    public static void updateRowHeight(JTable table, int margin) {
        final int rowCount = table.getRowCount();
        final int colCount = table.getColumnCount();
        for (int i = 0; i < rowCount; i++) {
            int maxHeight = 0;
            for (int j = 0; j < colCount; j++) {
                final TableCellRenderer renderer = table.getCellRenderer(i, j);
                maxHeight = Math.max(maxHeight, table.prepareRenderer(renderer, i, j).getPreferredSize().height);
            }
            table.setRowHeight(i, maxHeight + margin);
        }
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("IncorrectRowHeight");
        JComponent newContentPane = new IncorrectRowHeight();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

【讨论】:

  • 谢谢,这对于不同行需要不同高度的情况很有用。在我的情况下,这不是必需的。
猜你喜欢
  • 2011-10-02
  • 1970-01-01
  • 2020-12-29
  • 2013-02-10
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2017-09-01
  • 2012-02-25
相关资源
最近更新 更多