如何在 jtable 单元格中换行?
我正在尝试实现一个自定义 TableRenderer,如 this 中所述教程。 我想让渲染器对给定单元格太长的每个文本进行换行。 这个想法是,使用 TextArea 作为渲染器,因为它支持换行。 但是,以下代码的行为不符合预期:
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setText((String)value);
this.setWrapStyleWord(true);
this.setLineWrap(true);
return this;
}
}
我将此渲染器设置为
table.setDefaultRenderer(String.class, new LineWrapCellRenderer());
但单元格条目保持展开状态。 如果我将 this.setBackground(Color.YELLOW)
添加到 getTableCellRendererComponent()
方法, 所有细胞都如预期般呈黄色,但未包裹。
有任何想法吗?
更新:正如 Michael Borgwardt 在评论中所述,问题不是换行,而是行高:JTables 行的大小是固定的,因此如果单元格变得更高(因为文本现在是多个) -lines),我们必须增加行高。 但多少钱呢? 我会检查这是否值得另一个问题。 如果没有,我会在这里添加这个解决方案。
更新2:以下代码将确定行高(如果放置在getTableCellRendererComponent()
中):
int fontHeight = this.getFontMetrics(this.getFont()).getHeight();
int textLength = this.getText().length();
int lines = textLength / this.getColumns() +1;//+1, cause we need at least 1 row.
int height = fontHeight * lines;
table.setRowHeight(row, height);
I'm trying to implement a custom TableRenderer as described in this tutorial.
I'd like to have the renderer line-wrap each text that is to long for the given cell.
The idea is, to use a TextArea as renderer, as it supports line wrapping. However, the following code does not behave as expected:
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setText((String)value);
this.setWrapStyleWord(true);
this.setLineWrap(true);
return this;
}
}
I set this renderer with
table.setDefaultRenderer(String.class, new LineWrapCellRenderer());
But the cell entries stay unwrapped.
If I add this.setBackground(Color.YELLOW)
to the getTableCellRendererComponent()
method,
all cells are yellow as expected, but not wrapped.
Any ideas?
UPDATE: As Michael Borgwardt stated in the comments, the problem is not the line wrap, but the row height: JTables rows are fixed size, so if a cell is getting higher (cause the text is now multi-lined), we have to increase the row height.
But how much? I will check if this is worth another SO-question. If not, I will add this solution here.
Update2: The following code will determine the row height (if placed in getTableCellRendererComponent()
):
int fontHeight = this.getFontMetrics(this.getFont()).getHeight();
int textLength = this.getText().length();
int lines = textLength / this.getColumns() +1;//+1, cause we need at least 1 row.
int height = fontHeight * lines;
table.setRowHeight(row, height);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
问题在于 JTable 中的行高是固定的,因此这不仅仅是渲染器换行的问题; 我不确定为什么不这样做,但如果这样做,换行的文本将被裁剪 - 或者也许这正是您所看到的。 要调整行高,您需要单独设置它们。
这里'一些代码:
The problem is that the height of rows in JTable is fixed, so it's not just a matter of having a renderer that wraps; I'm not sure why it doesn't, but if it did, the wrapped text would be cropped - or maybe that's exactly what you're seeing. To adjust row heights, you need to set them individually.
Heres' some code for that:
您好,我遇到了同样的问题,但我实现的解决方案受到 Java 教程中用于绘制多行文本的示例的启发,并使用文本 API 在单元格上绘制文本。
http://java.sun.com/docs/books/tutorial /2d/text/drawmulstring.html
它也会调整行高的大小,但只有当此渲染器用于单列时它才能很好地发挥作用。
这就是我用来调用它来渲染我的表格的方式。
Hi I had your same problem but the solution I implemented is inspired by the sample available from the Java Tutorial for drawing multiline text and draws the text on the cell using the text APIs.
http://java.sun.com/docs/books/tutorial/2d/text/drawmulstring.html
It resizes row heigth too but it does it well only when this renderer is used for a single column.
And this is the way I used to invoke it for render my table.
除了这个问题之外,我还想与您分享多行单元格编辑器的解决方案。 它有点hacky(存储对编辑行的引用),但可以完成工作。
用法如下:
In addition to this question I'd like to share with you solution for multiline cell editor. It's a bit hacky (stores reference to edited row), but does the job.
Used as so:
您可以使用 JLabel 作为呈现器,并将文本插入 HTML 标记,然后在适当的位置添加
如何在 Swing 组件中使用 HTML
You could use a JLabel as a renderer and insert the text into a HTML tag and just add
<br>
where appropriateHow to use HTML in Swing Components
我偶然发现了同样的问题,我需要修改一下这里编写的代码,所以我附上我自己的版本:
I stumbled in this same problem, and I needed to modify a little the code that it was written here, so I attach my own version:
使用 Swing 正确实现此功能的唯一方法(我不了解 JavaFX:可能适用相同的原理)是理解并在渲染器组件上使用
setBounds
。我是通过反复试验得出这个结论的,而不是检查源代码。 但很明显,该方法负责布局文本(以任何字体)并计算然后实现自动换行。
上面的方法在这个 SSCCE 中工作得很好……但在现实世界中,随着字体更复杂、文本更多和表格更大,你就会开始遇到问题。 因此,我在下面建议使用新版本的 Listener 类以及新版本的渲染器(只是为了介绍复杂字体的使用......)。 如果有兴趣,请将这些替换到上面的 SSCCE 中......
The only way to implement this properly using Swing (I don't know about JavaFX: the same principles may possibly apply) is by understanding and using
setBounds
on the renderer component.I have come to this conclusion as a result of trial and error, rather than examining the source code. But is s clear that this method is responsible for laying out text (in whatever font) and calculating and then implementing word-wrapping).
The above works fine in this SSCCE... but in the real world, with more complex fonts, more text and larger tables you start to run into problems. I therefore propose below a new version of the Listener class along with a new version of the renderer (just to introduce the use of a complex font...). Substitute these into the above SSCCE if interested...
用 HTML 编写标题。 这是我拥有的一个例子。 我遇到的唯一问题是,如果我调整标题的高度,我很难让它们在
JPanel
中滚动。Write the headers in HTML. Here is an example of one that I have. The only issue that I am experiencing is I am having a hard time having them scroll in the
JPanel
if I adjust the height of the headers.如上所述,需要计算行高,但当前的解决方案可以改进。 事实上,它对我不起作用。
jtxt.getColumns()
返回零导致除以零。 这是一些我认为更干净的代码:As noted above the row height needs to be calculated but the current solution could be improved. In fact, it wasn't working for me.
jtxt.getColumns()
was returning zero causing a divide by zero. Here's some code I think is cleaner: