我想把一个字符串放在JTable
比给定单元格宽度更长的字符串中.如何rowHeight
动态设置以便我可以读取整个String?这是一个例子:
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
}
Run Code Online (Sandbox Code Playgroud)
在这里,您将看到对每个给定单元格的文本进行换行的代码
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;
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢,但我想动态实现RowHeight,具体取决于字符串长度...我想读取单元格中的整个字符串/文本.有什么建议?
我是java初学者,这是我的第一个问题.我很高兴得到答案.
kle*_*tra 13
使用JTextArea作为渲染组件时会出现几个问题(如果不是所有这些都已在本网站的几个QA中进行了解释).试着总结一下:
将单个行高调整为渲染组件的大小要求
基本上,要走的路是根据需要循环遍历单元格
OP编辑过的问题中的updateRowHeight方法很好.
JTextArea计算其preferredSize
为了获得一个合理的尺寸提示,它需要在另一个维度上以一些合理的尺寸"播种".也就是说,如果我们想要一个需要宽度的高度,那么必须在每个调用中完成.在表的上下文中,合理的宽度是当前列宽:
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
Run Code Online (Sandbox Code Playgroud)
动态调整高度
行高度完全确定在表/列/模型的某些稳定状态.因此,在初始化完成后以及任何其所依赖的状态发生更改时,您都要设置它(调用updateRowHeight)一次.
// TableModelListener
@Override
public void tableChanged(TableModelEvent e) {
updateRowHeights();
}
// TableColumnModelListener
@Override
public void columnMarginChanged(ChangeEvent e) {
updateRowHeights();
}
Run Code Online (Sandbox Code Playgroud)
注意
作为一般规则,getXXRendererComponent中的所有参数都是严格只读的,实现不得更改调用者的任何状态.从渲染器中更新rowHeight是错误的.
许多好的想法与其他答案以及相关问题相关联.
所以这就是我如何修改你的类以获得一个具有完全工作的自动行高的表:
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
}
Run Code Online (Sandbox Code Playgroud)
重要变化:
JFrame
可见之后才计算高度,因为在此之前我们可能没有正确的字体rowHeight
仅从event-dispatch-thread(SwingUtilities.isEventDispatchThread()
/ SwingUtilities.invokeLater()
)更改; 否则,RowHeightCellRenderer
当我们处于计算高度的中间时,表可能会为我们分配不同的值rowHeight
到20,所以我们可以再次缩小TableColumnModelListener
所以我们知道用户何时调整列的大小并缩小或增大rowHeight
s(如果不希望这样,你可以安全地删除监听器)此外,现在我只评估更改的行以进行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
Run Code Online (Sandbox Code Playgroud)
变化:
setSize()
在getTableCellRendererComponent()
因为否则物体不能正确地包裹preferedSize
根据最后一个字符的位置计算