Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在JTable中动态设置行高_Java_Swing_Jtable - Fatal编程技术网

Java 如何在JTable中动态设置行高

Java 如何在JTable中动态设置行高,java,swing,jtable,Java,Swing,Jtable,我想在JTable中放入一个比给定单元格宽度长的字符串。 如何动态设置行高,以便读取整个字符串? 以下是一个例子: import javax.swing.*; public class ExampleTable { public JPanel createTable() { JPanel totalGUI = new JPanel(); //define titles for table String[] title = {"TITLE

我想在
JTable
中放入一个比给定单元格宽度长的字符串。 如何动态设置
行高
,以便读取整个字符串? 以下是一个例子:

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
}
在这里,您将看到代码,其中一行打断了给定单元格中的每个文本

    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;
      }
    }
谢谢,但我想根据字符串长度动态实现行高。。。 我想读取单元格中的整个字符串/文本。有什么建议吗


我是java初学者,这是我的第一个问题。我很高兴能得到答案。

通常,当
行中的文本超过一行的
高度时,我们会设置
行高
,要设置行高,我们会执行以下操作:

table.setRowHeight(40);
我想在一个JTable中放入一个字符串,该字符串比给定的单元格宽度长。如何动态设置行高,以便读取整个字符串

要从jtable行读取完整字符串,您不需要设置
行高
,您需要设置
首选宽度。只需添加一行,如:

textTable.getColumnModel().getColumn(2).setPreferredWidth(300);
你就可以读整个字符串了


输出


使用JTextArea作为渲染组件时,会出现几个问题(大多数问题(如果不是全部的话)已经在本网站的几个QA中解释过了。试着总结一下:

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

基本上,方法是根据需要在细胞中循环,然后

  • 使用数据配置其渲染器
  • 询问渲染组件其首选大小
  • 将表格行高度设置为pref height
OP编辑问题中的updateRowHeight方法很好

JTextArea对其首选大小的计算

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

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
动态调整高度

它在表/列/模型的某个稳定状态下完全确定的行高。因此,您可以在初始化完成后以及它所依赖的任何状态发生更改时设置它(调用updaterowheeght)

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

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


一般来说,GetXXRenderComponent中的所有参数都是只读的,实现不能更改调用者的任何状态。从渲染器中更新行高是错误的,实际上JTextArea已经实现了根据宽度动态更改其高度所需的所有功能。当JTextArea在滚动窗格中使用时,可以看到此功能的作用,其中的高度会自动调整以适应滚动窗格的宽度。要使用此功能,必须首先将JTextArea的大小设置为某个宽度,然后JTextArea#getPreferredSize()将返回显示文本所需的高度(如果换行设置为true)

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

  • 将自定义TableCellRenderer添加到在TableCellRenderer#GetTableCellRenderComponent()中返回JTextArea的表中
  • 听一听下面解释的列的大小调整:
  • 更新列的行高,如下所述:
  • 在更新行高的过程中,首先设置新的宽度,然后获得首选高度,从而计算JTextArea所需的大小,如下面的代码段所示
  • 行高的更新功能:

    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);
        }
    }
    
    publicstaticvoidupdaterowheights(int列、int宽度、JTable表){
    对于(int row=0;row
    使用这种方法,不需要进一步计算列或行

    下面是OP示例表的完整代码,根据此实现进行了调整

    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);
        }
    }
    
    导入java.awt.Component;
    导入java.awt.Dimension;
    导入java.awt.event.MouseAdapter;
    导入java.awt.event.MouseEvent;
    导入javax.swing.JFrame;
    导入javax.swing.JPanel;
    导入javax.swing.JScrollPane;
    导入javax.swing.JTable;
    导入javax.swing.JTextArea;
    导入javax.swing.event.ChangeEvent;
    导入javax.swing.event.ListSelectionEvent;
    导入javax.swing.event.TableColumnModelEvent;
    导入javax.swing.event.TableColumnModelListener;
    导入javax.swing.table.AbstractTableModel;
    导入javax.swing.table.JTableHeader;
    导入javax.swing.table.TableCellRenderer;
    导入javax.swing.table.TableColumn;
    公共类示例{
    公共类RowHeightCellRenderer扩展了JTextArea,实现了TableCellRenderer{
    公共组件GetTableCellRenderComponent(
    JTable表,对象值,
    布尔值为已选,布尔值为焦点,
    整数行,整数列){
    可编辑设置(假);
    setLineWrap(真);
    setWrapStyleWord(true);
    如果(当选){
    挫折背景(table.getSelectionBackground());
    setForeground(table.getSelectionForeground());
    }否则
    
    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
    }
    
    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
    
    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;
        }
    }