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;
}
}