Java 如何在 JTable 中动态设置 RowHeight

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21723025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:17:43  来源:igfitidea点击:

How to set the RowHeight dynamically in a JTable

javaswingjtable

提问by Ramses

I want to put a String in a JTablethat is longer than the given cell-width. How can I set the rowHeightdynamically so that I can read the whole String? Here is an example:

我想将一个字符串放入JTable比给定单元格宽度更长的a中。如何rowHeight动态设置以便我可以读取整个字符串?下面是一个例子:

import javax.swing.*;

public class ExampleTable {

public JPanel createTable() {               
    JPanel totalGUI = new JPanel();

    //define titles for table
    String[] title = {"TITLE1", "TITLE2", "TITLE3"};

    //table data
    Object[][] playerdata = {       
    {new Integer(34), "Steve", "test test test"},
    {new Integer(32), "Patrick", "dumdi dumdi dummdi dumm di di didumm"},
    {new Integer(10), "Sarah", "blabla bla bla blabla bla bla blabla"},};

    //create object 'textTable'
    JTable textTable = new JTable(playerdata,title);

    //set column width
    textTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
    textTable.getColumnModel().getColumn(0).setPreferredWidth(60);
    textTable.getColumnModel().getColumn(1).setPreferredWidth(60);
    textTable.setDefaultRenderer(String.class, new RowHeightCellRenderer());

    //scrollbar
    JScrollPane scrollPane = new JScrollPane(textTable);

    totalGUI.add(scrollPane);               
    return totalGUI;
}

private static void createAndShowGUI() {

    //create main frame
    JFrame mainFrame = new JFrame("");
    ExampleTable test = new ExampleTable();

    JPanel totalGUI = new JPanel();
    totalGUI = test.createTable();

    //visible mode
    mainFrame.add(totalGUI); //integrate main panel to main frame
    mainFrame.pack();
    mainFrame.setVisible(true);     
}


public static void main (String[] args) {               

    createAndShowGUI();     

}//main
}

And here you'll see the code which line-breaks each text that is to long for the given cell

在这里,您将看到对给定单元格长的每个文本进行换行的代码

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


    public class RowHeightCellRenderer extends JTextArea implements TableCellRenderer
    {
      /**
         * 
         */
        private static final long serialVersionUID = 1L;

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

thank you but I want to implement the RowHeight dynamically, depending on String length... I want to read the whole String/text in the cell. any suggestions?

谢谢,但我想根据字符串长度动态实现 RowHeight...我想读取单元格中的整个字符串/文本。有什么建议?

I'm java beginner and this is my first question. I would be delighted I get an answer.

我是 Java 初学者,这是我的第一个问题。我会很高兴得到答复。

采纳答案by kleopatra

There are several issues when using a JTextArea as rendering component (and most if not all of them already explained in several QA's on this site). Trying to sum them up:

使用 JTextArea 作为渲染组件时存在几个问题(并且大多数(如果不是全部)已经在本站点的几个 QA 中进行了解释)。试图总结它们:

Adjust individual row height to the size requirements of the rendering component

根据渲染组件的大小要求调整单个行高

Basically, the way to go is to loop through the cells as needed, then

基本上,要走的路是根据需要循环遍历单元格,然后

  • configure its renderer with the data
  • ask the rendering component for its preferred size
  • set the table row height to the pref height
  • 使用数据配置其渲染器
  • 向渲染组件询问其首选大小
  • 将表格行高设置为首选项高度

The updateRowHeight method in the OP's edited question is just fine.

OP 编辑​​的问题中的 updateRowHeight 方法很好。

JTextArea's calculation of its preferredSize

JTextArea 对其preferredSize 的计算

to get a reasonable sizing hint for one dimension, it needs to be "seeded" with some reasonable size in the other dimension. That is if we want the height it needs a width, and that must be done in each call. In the context of a table, a reasonable width is the current column width:

为了获得一个维度的合理大小提示,需要在另一个维度中“播种”一些合理的大小。也就是说,如果我们想要高度,它需要一个宽度,并且必须在每次调用中完成。在表格的上下文中,合理的宽度是当前列宽:

public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
    ... // configure visuals
    setText((String) value);
    setSize(table.getColumnModel().getColumn(column).getWidth(),
            Short.MAX_VALUE);
    return this;
}// getTableCellRendererComponent

Dynamic adjustment of the height

高度动态调整

The row height it fully determined in some steady state of the table/column/model. So you set it (call updateRowHeight) once after the initialization is completed and whenever any of the state it depends on is changed.

它在表/列/模型的某些稳定状态下完全确定的行高。所以你在初始化完成后设置一次(调用 updateRowHeight),每当它依赖的任何状态发生改变时。

// TableModelListener
@Override
public void tableChanged(TableModelEvent e) {
    updateRowHeights();
}

// TableColumnModelListener
@Override
public void columnMarginChanged(ChangeEvent e) {
    updateRowHeights();
}

Note

笔记

As a general rule, all parameters in the getXXRendererComponent are strictly read-only, implementations must notchange any state of the caller. Updating the rowHeight from within the renderer is wrong.

作为一般规则,getXXRendererComponent 中的所有参数都是严格只读的,实现不能改变调用者的任何状态。从渲染器中更新 rowHeight 是错误的

回答by ravibagul91

Normally we are setting the RowHeightwhen the text in the rowgoes beyond the heightof a row, to set the height of a row we do this:

通常我们会设置RowHeight当文本中的文本row超出height行的时候,要设置行的高度,我们这样做:

table.setRowHeight(40);

I want to put a String in a JTable that is longer than the given cell-width. How can I set the rowHeight dynamically so that I can read the whole String?

我想在 JTable 中放置一个比给定的 cell-width 长的 String 。如何动态设置 rowHeight 以便我可以读取整个 String

To read complete string from the jtable row you don't need to set RowHeightyou need to set the PreferredWidthof a columnas you are already doing so. Just add a line like:

要从不需要设置的 jtable 行读取完整的字符串,RowHeight您需要设置PreferredWidtha ,column因为您已经这样做了。只需添加一行,如:

textTable.getColumnModel().getColumn(2).setPreferredWidth(300);

And you will be able to read the whole string.

您将能够读取整个字符串。



Output

输出

output

输出

回答by Balder

Actually JTextArea already implements all the features required to dynamically change its height based on its width. One can see this functionality in action, when JTextArea is used inside a ScrollPane, where its height is automatically adjusted to fit the width of the ScrollPane. To use this feature, one has to first set the size of the JTextArea to some width and then JTextArea#getPreferredSize() will return the required height to display the text (if line wrap is set to true).

实际上 JTextArea 已经实现了根据其宽度动态改变其高度所需的所有功能。当在 ScrollPane 中使用 JTextArea 时,可以看到此功能在起作用,其高度会自动调整以适合 ScrollPane 的宽度。要使用此功能,必须首先将 JTextArea 的大小设置为某个宽度,然后 JTextArea#getPreferredSize() 将返回显示文本所需的高度(如果换行设置为 true)。

So to dynamically change the row height of a JTable based on its width, one can do the following:

因此,要根据宽度动态更改 JTable 的行高,可以执行以下操作:

  1. Add a custom TableCellRenderer to the table that returns a JTextArea in TableCellRenderer#getTableCellRendererComponent()
  2. Listen to the resizing of the columns as explained here: Java JTable detect Column re-sized by user
  3. Update the row heights of the columns as explained here: Auto adjust the height of rows in a JTable
  4. During the update of the row heights, one calculates the required size of the JTextArea by first setting the new width and then getting the preferred height as shown in the following code snippet
  1. 在 TableCellRenderer#getTableCellRendererComponent() 中向返回 JTextArea 的表中添加自定义 TableCellRenderer
  2. 按照此处的说明收听列的调整大小:Java JTable 检测用户调整大小的列
  3. 按照此处的说明更新列的行高:自动调整 JTable 中的行高
  4. 在行高更新期间,首先设置新宽度,然后获取首选高度,计算 JTextArea 所需的大小,如下面的代码片段所示

Update function of the row heights:

行高更新函数:

public static void updateRowHeights(int column, int width, JTable table){
    for (int row = 0; row < table.getRowCount(); row++) {
        int rowHeight = table.getRowHeight();
        Component comp = table.prepareRenderer(table.getCellRenderer(row, column), row, column);
        Dimension d = comp.getPreferredSize();
            // first set the size to the new width
        comp.setSize(new Dimension(width, d.height));
            // then get the preferred size
        d = comp.getPreferredSize();
        rowHeight = Math.max(rowHeight, d.height);
            // finally set the height of the table
        table.setRowHeight(row, rowHeight);
    }
}

With this approach, no further calculations of colums or rows are necessary.

使用这种方法,不需要进一步计算列或行。

Here is the complete code of the OP's ExampleTable, adjusted to this implementation.

这是 OP 的 ExampleTable 的完整代码,已针对此实现进行了调整。

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class ExampleTable {

    public class RowHeightCellRenderer extends JTextArea implements TableCellRenderer {

        public Component getTableCellRendererComponent(
                JTable table, Object value,
                boolean isSelected, boolean hasFocus,
                int row, int column) {

            setEditable(false);
            setLineWrap(true);
            setWrapStyleWord(true);

            if (isSelected) {
                setBackground(table.getSelectionBackground());
                setForeground(table.getSelectionForeground());
            } else {
                setBackground(table.getBackground());
                setForeground(table.getForeground());
            }

            setText(value.toString());
            return this;
        }
    }

    public static void updateRowHeights(int column, int width, JTable table){
        for (int row = 0; row < table.getRowCount(); row++) {
            int rowHeight = table.getRowHeight();
            Component comp = table.prepareRenderer(table.getCellRenderer(row, column), row, column);
            Dimension d = comp.getPreferredSize();
            comp.setSize(new Dimension(width, d.height));
            d = comp.getPreferredSize();
            rowHeight = Math.max(rowHeight, d.height);
            table.setRowHeight(row, rowHeight);
        }
    }

    public JPanel createTable() {

        JPanel totalGUI = new JPanel();

        //define titles for table
        final String[] columnNames = {"TITLE1", "TITLE2", "TITLE3"};

        //table data
        final Object[][] rowData = {       
                {new Integer(34), "Steve", "test test test"},
                {new Integer(32), "Patrick", "dumdi dumdi dummdi dumm di di didumm"},
                {new Integer(10), "Sarah", "blabla bla bla blabla bla bla blabla"},};

        AbstractTableModel model = new AbstractTableModel() {
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                return String.class;
            }

            public String getColumnName(int column) { return columnNames[column].toString(); }
            public int getRowCount() { return rowData.length; }
            public int getColumnCount() { return columnNames.length; }
            public Object getValueAt(int row, int col) { return rowData[row][col]; }
            public boolean isCellEditable(int row, int column) { return true; }
            public void setValueAt(Object value, int row, int col) {
                rowData[row][col] = value;
                fireTableCellUpdated(row, col);
            }
        };

        //create object 'textTable'
        final JTable textTable = new JTable();

        textTable.setDefaultRenderer(String.class, new RowHeightCellRenderer());
        textTable.setModel(model);

        //set column width
        textTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
        textTable.getColumnModel().getColumn(0).setPreferredWidth(60);
        textTable.getColumnModel().getColumn(1).setPreferredWidth(60);

        ColumnListener cl = new ColumnListener(){

            @Override
            public void columnMoved(int oldLocation, int newLocation) {
            }

            @Override
            public void columnResized(int column, int newWidth) {
                updateRowHeights(column, newWidth, textTable);
            }

        };

        textTable.getColumnModel().addColumnModelListener(cl);
        textTable.getTableHeader().addMouseListener(cl);

        // initial update of row heights
        TableColumn c = textTable.getColumnModel().getColumn(2);
        updateRowHeights(2, c.getWidth(), textTable);

        //scrollbar
        JScrollPane scrollPane = new JScrollPane(textTable);

        totalGUI.add(scrollPane);               
        return totalGUI;
    }

    private static void createAndShowGUI() {

        //create main frame
        JFrame mainFrame = new JFrame("");
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ExampleTable test = new ExampleTable();

        JPanel totalGUI = new JPanel();
        totalGUI = test.createTable();

        //visible mode
        mainFrame.add(totalGUI); //integrate main panel to main frame
        mainFrame.pack();
        mainFrame.setVisible(true);     
    }


    public static void main (String[] args) {               

        createAndShowGUI();     

    }//main


    abstract class ColumnListener extends MouseAdapter implements TableColumnModelListener {

        private int oldIndex = -1;
        private int newIndex = -1;
        private boolean dragging = false;

        private boolean resizing = false;
        private int resizingColumn = -1;
        private int oldWidth = -1;

        @Override
        public void mousePressed(MouseEvent e) {
            // capture start of resize
            if(e.getSource() instanceof JTableHeader) {
                JTableHeader header = (JTableHeader)e.getSource();
                TableColumn tc = header.getResizingColumn();
                if(tc != null) {
                    resizing = true;
                    JTable table = header.getTable();
                    resizingColumn = table.convertColumnIndexToView( tc.getModelIndex());
                    oldWidth = tc.getPreferredWidth();
                } else {
                    resizingColumn = -1;
                    oldWidth = -1;
                }
            }   
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // column moved
            if(dragging && oldIndex != newIndex) {
                columnMoved(oldIndex, newIndex);
            }
            dragging = false;
            oldIndex = -1;
            newIndex = -1;

            // column resized
            if(resizing) {
                if(e.getSource() instanceof JTableHeader) {
                    JTableHeader header = (JTableHeader)e.getSource();
                    TableColumn tc = header.getColumnModel().getColumn(resizingColumn);
                    if(tc != null) {
                        int newWidth = tc.getPreferredWidth();
                        if(newWidth != oldWidth) {
                            columnResized(resizingColumn, newWidth);
                        }
                    }
                }   
            }
            resizing = false;
            resizingColumn = -1;
            oldWidth = -1;
        }

        @Override
        public void columnAdded(TableColumnModelEvent e) {      
        }

        @Override
        public void columnRemoved(TableColumnModelEvent e) {        
        }

        @Override
        public void columnMoved(TableColumnModelEvent e) {
            // capture dragging
            dragging = true;
            if(oldIndex == -1){
                oldIndex = e.getFromIndex();
            }

            newIndex = e.getToIndex();  
        }

        @Override
        public void columnMarginChanged(ChangeEvent e) {
        }

        @Override
        public void columnSelectionChanged(ListSelectionEvent e) {
        }

        public abstract void columnMoved(int oldLocation, int newLocation);
        public abstract void columnResized(int column, int newWidth);
    }
}

Note, that I reused and changed some of the code from Java JTable detect Column re-sized by userand Auto adjust the height of rows in a JTable.

请注意,我重用并更改了Java JTable 检测 Column 由用户重新调整大小自动调整 JTable 中行的高度的一些代码。

回答by TheConstructor

Many good ideas are linked in other answers and also in the related questions.

许多好的想法都与其他答案以及相关问题相关联。

So here is how I modified you classes to get a table with fully working auto-line-heights:

所以这里是我如何修改你的类以获得一个具有完全工作自动行高的表格:

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

public class ExampleTable implements TableModelListener {
    JTable textTable;

    public JPanel createTable() {
        JPanel totalGUI = new JPanel();

        //define titles for table
        String[] title = {"TITLE1", "TITLE2", "TITLE3"};

        //table data
        Object[][] playerdata = {
                {new Integer(3), "Steve", "test test test"},
                {new Integer(32), "Patrick", "du hu hu hu hu hu hu hu uh u kkkkkk oooo pppp"},
                {new Integer(10), "Sarah", "xxxxxxxxxxxxx aaaaaaaaaa bbbbbbbbbbbb dddddddddddd xxxxxxx gggewr  eeeeeeeeee22 ddd g fffffff zzzzzzz"},};

        //define tablemodel
        TableModel model = new DefaultTableModel(playerdata, title);

        //create object 'textTable'
        textTable = new JTable(model);

        //set column width
        textTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        textTable.getColumnModel().getColumn(0).setPreferredWidth(17);
        textTable.getColumnModel().getColumn(1).setPreferredWidth(45);
        textTable.getColumnModel().getColumn(2).setPreferredWidth(200);

        //put line breaks if string is longer than cell-width
        RowHeightCellRenderer dynRow = new RowHeightCellRenderer();
        textTable.getColumnModel().getColumn(2).setCellRenderer(dynRow);

        // No more data changes; install listeners
        textTable.getModel().addTableModelListener(this);
        textTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
            /**
             * We only need to recalculate once; so track if we are already going to do it.
             */
            boolean columnHeightWillBeCalculated = false;

            @Override
            public void columnAdded(TableColumnModelEvent e) {
            }

            @Override
            public void columnRemoved(TableColumnModelEvent e) {
            }

            @Override
            public void columnMoved(TableColumnModelEvent e) {
            }

            @Override
            public void columnMarginChanged(ChangeEvent e) {
                if (!columnHeightWillBeCalculated && textTable.getTableHeader().getResizingColumn() != null) {
                    columnHeightWillBeCalculated = true;
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            // textTable.getTableHeader().getResizingColumn() is != null as long as the user still is holding the mouse down
                            // To avoid going over all data every few milliseconds wait for user to release
                            if (textTable.getTableHeader().getResizingColumn() != null) {
                                SwingUtilities.invokeLater(this);
                            } else {
                                tableChanged(null);
                                columnHeightWillBeCalculated = false;
                            }
                        }
                    });
                }
            }

            @Override
            public void columnSelectionChanged(ListSelectionEvent e) {
            }
        });

        //scrollbar
        JScrollPane scrollPane = new JScrollPane(textTable);
        totalGUI.add(scrollPane);
        return totalGUI;
    }

    public void tableChanged(TableModelEvent e) {
        final int first;
        final int last;
        if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) {
            // assume everything changed
            first = 0;
            last = textTable.getModel().getRowCount();
        } else {
            first = e.getFirstRow();
            last = e.getLastRow() + 1;
        }
        // GUI-Changes should be done through the EventDispatchThread which ensures all pending events were processed
        // Also this way nobody will change the text of our RowHeightCellRenderer because a cell is to be rendered
        if(SwingUtilities.isEventDispatchThread()) {
            updateRowHeights(first, last);
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    updateRowHeights(first, last);
                }
            });
        }
    }

    private void updateRowHeights(final int first, final int last) {
    /*
     * Auto adjust the height of rows in a JTable.
     * The only way to know the row height for sure is to render each cell
     * to determine the rendered height. After your table is populated with
     * data you can do:
     *
     */
        for (int row = first; row < last; row++) {
            int rowHeight = 20;
            for (int column = 0; column < textTable.getColumnCount(); column++) {
                Component comp = textTable.prepareRenderer(textTable.getCellRenderer(row, column), row, column);
                rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
            }
            if(rowHeight != textTable.getRowHeight(row)) {
                textTable.setRowHeight(row, rowHeight);
                System.out.println("neue Zeilenh?he: "+rowHeight+" bei Zeile: "+row);
            }
        }
    }

    private static void createAndShowGUI() {

        //create main frame
        JFrame mainFrame = new JFrame("");
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ExampleTable test = new ExampleTable();
        JPanel totalGUI = new JPanel();
        totalGUI = test.createTable();

        //visible mode
        mainFrame.add(totalGUI); //integrate main panel to main frame
        mainFrame.pack();
        mainFrame.setVisible(true);

        //adjust dynamically the Row height of each cell
        test.tableChanged(null);
    }


    public static void main (String[] args) {
        createAndShowGUI();
    }//main
}

Important changes:

重要变化:

  • calculate height only after JFrameis visible because we may not have the correct font before then
  • change rowHeightonly from event-dispatch-thread (SwingUtilities.isEventDispatchThread()/SwingUtilities.invokeLater()); otherwise the table might assign different values to our RowHeightCellRendererwhile we are in the middle of calculating height
  • initalize rowHeightto 20, so we can shrink again
  • TableColumnModelListenerso we know when the user resizes a column and shrink or grow rowHeights (you can safely remove the Listener if this is undesired)
  • 仅在JFrame可见之后计算高度,因为在此之前我们可能没有正确的字体
  • rowHeight仅从事件调度线程 ( SwingUtilities.isEventDispatchThread()/ SwingUtilities.invokeLater())更改;否则,RowHeightCellRenderer当我们正在计算高度时,表格可能会为我们分配不同的值
  • 初始化rowHeight为 20,所以我们可以再次缩小
  • TableColumnModelListener所以我们知道用户何时调整列大小并缩小或增加rowHeights(如果不希望出现这种情况,您可以安全地删除监听器)

Also now I only evaluate changed rows for TableModelchanges

另外现在我只评估更改的行的TableModel更改

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

public class RowHeightCellRenderer extends JTextArea implements TableCellRenderer {

    private static final long serialVersionUID = 1L;


    public RowHeightCellRenderer() {
        setLineWrap(true);
        setWrapStyleWord(true);
    }//constructor

    public Component getTableCellRendererComponent (JTable table,
                                                    Object value,
                                                    boolean isSelected,
                                                    boolean hasFocus,
                                                    int row,
                                                    int column ) {
        this.setText((String) value);

        if(isSelected) {
            this.setBackground(table.getSelectionBackground());
            this.setForeground(table.getSelectionForeground());
        } else {
            this.setBackground(table.getBackground());
            this.setForeground(table.getForeground());
        }

        final int columnWidth = table.getColumnModel().getColumn(column).getWidth();
        final int rowHeight = table.getRowHeight(row);
        this.setSize(columnWidth, rowHeight);

        this.validate();
        return this;
    }//getTableCellRendererComponent

    @Override
    public Dimension getPreferredSize() {
        try {
            // Get Rectangle for position after last text-character
            final Rectangle rectangle = this.modelToView(getDocument().getLength());
            if(rectangle != null) {
                return new Dimension(this.getWidth(),
                                     this.getInsets().top + rectangle.y + rectangle.height +
                                                                  this.getInsets().bottom);
            }
        } catch (BadLocationException e) {
            e.printStackTrace();  // TODO: implement catch
        }

        return super.getPreferredSize();
    }
}//RowHeightCellRenderer

Changes:

变化:

  • setSize()in getTableCellRendererComponent()as otherwise the object is unable to wrap correctly
  • calculate preferedSizeaccording to position of last character
  • setSize()getTableCellRendererComponent()因为否则物体不能正确地包裹
  • preferedSize根据最后一个字符的位置计算

回答by Ned Howley

I find it simplest to adjust the row height from inside the component renderer, like this:

我发现从组件渲染器内部调整行高最简单,如下所示:

public class RowHeightCellRenderer extends JTextArea implements TableCellRenderer
{
    public Component getTableCellRendererComponent(JTable table, Object 
            value, boolean isSelected, boolean hasFocus,
            int row, int column) {

        setText(value.toString());

        // Set the component width to match the width of its table cell
        // and make the height arbitrarily large to accomodate all the contents
        setSize(table.getColumnModel().getColumn(column).getWidth(), Short.MAX_VALUE);

        // Now get the fitted height for the given width
        int rowHeight = this.getPreferredSize().height;

        // Get the current table row height
        int actualRowHeight = table.getRowHeight(row);

        // Set table row height to fitted height.
        // Important to check if this has been done already
        // to prevent a never-ending loop.
        if (rowHeight != actualRowHeight) {
           table.setRowHeight(row, rowHeight);
        }

        return this;
    }
}

This will also work for a renderer which returns a JTextPane.

这也适用于返回JTextPane.