在 TableCellRenderer 中使用自定义 Swing JComponent
好的,我知道如何制作一个简单的自定义 JComponent。 我知道如何重写 TableCellRenderer。 我似乎无法将两者结合起来。
这是我创建的一个示例 JComponent
:
public static class BarRenderer extends JComponent
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
this.xmin=xmin;
this.xmax=xmax;
}
@Override protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.drawRect(r.x, r.y,
(int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
}
public void setXval(double x) {
this.xval = x;
repaint();
}
public double getXval() { return xval; }
}
它作为独立的 JComponent 工作得很好。 我调用 setXval(something) ,它更新得很好。 (编辑:我有一个定期更新数据的 Swing Timer)
但是如果这个组件是我在 TableCellRenderer.getTableCellRendererComponent() 中返回的组件,那么它只会在我单击相关单元格时重新绘制。 是什么赋予了? 我一定遗漏了一些非常简单的东西。
OK, I know how to make a simple custom JComponent. I know how to override a TableCellRenderer. I can't seem to combine the two.
Here's a sample JComponent
I created:
public static class BarRenderer extends JComponent
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
this.xmin=xmin;
this.xmax=xmax;
}
@Override protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Rectangle r = g.getClipBounds();
g.drawRect(r.x, r.y,
(int)(r.width * ((xval-xmin)/(xmax-xmin))), r.height);
}
public void setXval(double x) {
this.xval = x;
repaint();
}
public double getXval() { return xval; }
}
It works fine as a standalone JComponent. I call setXval(something)
and it updates just fine. (edit: I have a Swing Timer that updates the data periodically)
But if this component is something I return in TableCellRenderer.getTableCellRendererComponent(), then it only repaints when I click on the cell in question. What gives? I must be leaving out something really simple.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
出于性能原因,JTable 重用渲染器组件来绘制多个单元格 - 因此,当您在 JTable 中看到该组件时,它实际上并不存在于传统意义上的容器中存在于某个位置的组件中。 这意味着在渲染器组件上调用 repaint() 不会执行任何操作。
最有效的选择是将条形的整数值存储在 TableModel 中。 然后,您的 TableCellRenderer 将如下所示:
然后,您可以更改 TableModel 中的 Integer,它将触发栏的重新绘制(您可能需要 TableModel.fireTableCellUpdated ,具体取决于您正在使用的 TableModel 实现)。
For performance reasons a JTable reuses renderer components to paint multiple cells - so when you see the component in the JTable it isn't actually there in the traditional sense of a Component in a Container which is present at a location. This means that calling repaint() on the renderer component does nothing.
The most effective option would be to store the Integer value of the bar in your TableModel. Your TableCellRenderer would then look something like this:
Then you could change the Integer in your TableModel and it would trigger a repaint of the bar (you may need a TableModel.fireTableCellUpdated dependent on the TableModel implementation you are using).
你们俩(Russ Hayward 和 Andrew)都提供了帮助,关键本质上是执行以下操作:
TableCellRenderer.getTableCellRendererComponent()
中存储单元格的状态,以便稍后渲染(长期存储在 TableModel 中)JComponent.PaintComponent()
TableCellRenderer.getTableCellRendererComponent()
中存储单元格的状态并返回此值;
这是我现在可以使用的代码的相关摘录:
Both of you (Russ Hayward and Andrew) helped, the key was essentially to do the following:
fireTableCellUpdated()
is calledTableCellRenderer.getTableCellRendererComponent()
store the cell's state for purposes of being rendering soon after (long-term storage is in the TableModel)JComponent.PaintComponent()
TableCellRenderer.getTableCellRendererComponent()
you store the cell's state andreturn this;
Here's the relevant excerpt of my code that now works:
如果您制作一个包含 3 行的表格,每行都有不同的 Xval,那么它最初渲染器是否正确,这意味着每个单元格都有不同的外观栏?
当您说除非单击它否则它不会重新绘制时,您的基础数据是否发生了一些应该导致数据(渲染栏)的视觉显示发生变化的事情?
如果数据发生了变化,但表没有立即重新渲染,那么我会说你的 TableModel 无法正常工作。
底层数据变化-> TableModel 更改 -> 触发 TableModelEvent -> JTable 重新渲染
查看 TableModel tuturial: http: //java.sun.com/docs/books/tutorial/uiswing/components/table.html#data
确保您所做的一切都是正确的。
If you make a table with say 3 rows, each having a different Xval, then does it initially renderer correctly, meaning each cell has a different looking bar?
When you say it does not repaint unless you click it, has something happened to your underlying data that should have caused the visual display of the data (the rendered bar) to change?
If the data changed, but the table does not immediatley re-render, then I would say that your TableModel is not working properly.
underlying data changes -> TableModel changes -> fires TableModelEvent -> JTable re-renders
Look at the TableModel tuturial: http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#data
to make sure you are doing everything correct.