具有自动高度的多行 JTable 单元格 - 超大第一行
我正在使用 Swing 开发 Java 桌面应用程序 (jdk1.6)。我的问题是关于 JTable 中具有自动调整单元格高度属性的多行单元格(文本换行)。
我已经可以通过这种方式实现这个结构:
- 表有它自己的单元格渲染器。
- 单元格是 JTextArea,wraptext=true
- 在将文本插入单元格后,我对 JTextArea 中的行进行计数,并相应地调整相关行的行高。
- 单元格宽度会自动调整。 (根据首选大小)
此结构有两个问题:
1)在程序执行过程中,它可以计算行数并适当调整行高。
但在第一次初始化(第一次 setModel())时,它计算表的“第一个单元格”的行数,即 (0,0),比实际要多得多。我调试了代码,发现它计算文本中的字母并乘以行高16。(就好像单元格的宽度是1个字母)。最后我得到了非常非常高的第一排。其他行都没问题。
当我不向 (0,0) 插入任何文本时,不会出现问题。
2)当我禁用表格自动调整大小属性并手动确定单元格宽度时,行计数不起作用。
这是我的单元格渲染器:
public class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
private JTable DependentTable;
public MultiLineCellRenderer() {
DependentTable=null;
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
(...) //some background color adjustments
setText((value == null) ? "" : value.toString());
int numOfLines = getWrappedLines(this); // Counting the lines
int height_normal = table.getRowHeight(row);// read the height of the row
if(DependentTable == null) // for this case always null
{
if (height_normal < numOfLines*16)
{
table.setRowHeight(row,numOfLines*16);
}
}
else
(...)
return this;
}
这是我如何计算行数:
public static int getWrappedLines(JTextArea component)
{
View view = component.getUI().getRootView(component).getView(0);
int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
int lineHeight = component.getFontMetrics( component.getFont() ).getHeight();
return preferredHeight / lineHeight;
}
------------------------------------------------ -
我将行调整代码删除到类的外部。该表现在有一个模型侦听器。此时第一行并不是特别大。调用此方法是可行的,但问题在于计算换行数。每次我用很长的文本填充单元格时,该行都会正确换行,但我的计数器返回 1。(换行计数器的代码在上面。与渲染器中的相同。但它在那里工作得很好)
这是我的模型侦听器:
public class ModelListener implements TableModelListener {
JTable mainTable;
JTable depTable;
public ModelListener(JTable m, JTable d) {
mainTable = m;
depTable = d;
}
public ModelListener(JTable m){
mainTable = m;
depTable = null;
}
public void tableChanged(TableModelEvent tme) {
int fRow = tme.getFirstRow();
int col = tme.getColumn();
JTextArea cellArea = (JTextArea)mainTable.getDefaultRenderer(Object.class);
int numOfLines = getWrappedLines(cellArea); //countLines();
int height_normal = mainTable.getRowHeight(fRow);
System.out.println("h normal:"+height_normal);
System.out.println("numLines:"+numOfLines);
System.out.println("value:"+mainTable.getModel().getValueAt(fRow, col));
System.out.println("width:"+cellArea.getPreferredSize().width);
if(depTable == null)
{
if (height_normal < numOfLines*16)
{
mainTable.setRowHeight(fRow,numOfLines*16);
}
}
else
{
//(---)
}
mainTable.repaint();
}
打印行的结果:
- preferredHeight: 15 // 来自换行函数
- lineHeight: 15 // 来自换行函数
- 正常时:25
- 行数:1
- value:loooooooooooooooooooooonng tessssssssssssssssssssssssst // 似乎有 2 行
- 宽度:104
提前感谢 :)
Isil
I am developing a Java Desktop Application (jdk1.6) with Swing. My problem is about Multi-line cells(text-wrapping) with auto-adjusting cell height property in JTable.
I could already implement this structure in this way:
- Table has its own cellrenderer.
- Cells are JTextArea with wraptext=true
- I count the rows in the JTextArea after inserting the text to the cell and adjust the row height of related row accordingly.
- Cell width is automatically adjusted. (from preferred size)
2 problems about this structure:
1) During the execution of the program, it can count the rows and adjusts the row height properly.
But at the first initialization (first setModel()) it calculates the row count of "the first cell" of the table,i.e (0,0), much more than it is. I have debugged the code and found that it counts the letters in the text and multiplies with row height 16. (as if the width of cell was 1 letter) . At the end I get a very very high first row. Other rows are ok.
When I doesn't insert any text to (0,0), no problem occurs.
2) Row count doesn't work when I disable the table auto-resize property and determine the cell widths manually.
Here is my cell renderer:
public class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
private JTable DependentTable;
public MultiLineCellRenderer() {
DependentTable=null;
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
(...) //some background color adjustments
setText((value == null) ? "" : value.toString());
int numOfLines = getWrappedLines(this); // Counting the lines
int height_normal = table.getRowHeight(row);// read the height of the row
if(DependentTable == null) // for this case always null
{
if (height_normal < numOfLines*16)
{
table.setRowHeight(row,numOfLines*16);
}
}
else
(...)
return this;
}
Here how I calculate number of rows:
public static int getWrappedLines(JTextArea component)
{
View view = component.getUI().getRootView(component).getView(0);
int preferredHeight = (int)view.getPreferredSpan(View.Y_AXIS);
int lineHeight = component.getFontMetrics( component.getFont() ).getHeight();
return preferredHeight / lineHeight;
}
------------------------------------
I removed the row-adjusting-code to the outside of the class. The table has a Model Listener now. The first row is not extreme large in this time. Calling this method works but the problem is about counting the wrapped lines. Every time I fill in the cell with a very long text, the line is wrapped properly but my counter returns 1. (code the wrappedline counter is above. same as the one in renderer. But It worked fine there)
here is my model listener:
public class ModelListener implements TableModelListener {
JTable mainTable;
JTable depTable;
public ModelListener(JTable m, JTable d) {
mainTable = m;
depTable = d;
}
public ModelListener(JTable m){
mainTable = m;
depTable = null;
}
public void tableChanged(TableModelEvent tme) {
int fRow = tme.getFirstRow();
int col = tme.getColumn();
JTextArea cellArea = (JTextArea)mainTable.getDefaultRenderer(Object.class);
int numOfLines = getWrappedLines(cellArea); //countLines();
int height_normal = mainTable.getRowHeight(fRow);
System.out.println("h normal:"+height_normal);
System.out.println("numLines:"+numOfLines);
System.out.println("value:"+mainTable.getModel().getValueAt(fRow, col));
System.out.println("width:"+cellArea.getPreferredSize().width);
if(depTable == null)
{
if (height_normal < numOfLines*16)
{
mainTable.setRowHeight(fRow,numOfLines*16);
}
}
else
{
//(---)
}
mainTable.repaint();
}
The result of printlines:
- preferredHeight: 15 // from wrapped lines function
- lineHeight: 15 // from wrapped lines function
- h normal:25
- numLines:1
- value:looooooooooooooooooooooonng tesssssssssssssssssssssssst // appears to be 2 lines
- width:104
Thanks in advance :)
Isil
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只是现在就拥有解决方案,即使几年后,它也可能对其他人有所帮助。您可以设置固定行数或使用适合内容的动态行数。您应该很容易以任何方式扩展它。
Just for having the solution at Hand right now, even after a few years, it may help some others. you can set a fixed number of rows or use a dynamic row Count which fits the Content. it should be easy for you to Extend this in any way.