Java 在TableCellRenderer中使用自定义Swing JComponent
好的,我知道如何制作一个简单的定制组件。我知道如何覆盖TableCellRenderer。我似乎无法将两者结合起来 下面是我创建的一个示例Java 在TableCellRenderer中使用自定义Swing JComponent,java,swing,jcomponent,tablecellrenderer,Java,Swing,Jcomponent,Tablecellrenderer,好的,我知道如何制作一个简单的定制组件。我知道如何覆盖TableCellRenderer。我似乎无法将两者结合起来 下面是我创建的一个示例JComponent public static class BarRenderer extends JComponent { final private double xmin; final private double xmax; private double xval; public BarRenderer(double
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(某物)
,它更新得很好。(编辑:我有一个摆动计时器,定期更新数据)
但是如果这个组件是我在TableCellRenderer.GetTableCellRenderComponent()中返回的,那么它只在我单击相关单元格时重新绘制。有什么好处?我必须略去一些非常简单的东西。如果你制作一个包含3行的表格,每行都有一个不同的Xval,那么它一开始是否正确,这意味着每个单元格都有一个不同的外观条 当您说除非单击它,否则它不会重新绘制时,您的基础数据是否发生了本应导致数据(渲染条)的视觉显示发生更改的情况 如果数据发生了更改,但表没有立即重新呈现,那么我会说您的TableModel工作不正常 基础数据更改->表格模型更改->激发表格模型事件->JTable重新呈现 查看TableModel tuturial:
确保你做的每件事都是正确的。如果你做了一个表,比如说有3行,每行都有不同的Xval,那么它一开始是否正确,这意味着每个单元格都有不同的外观条 当您说除非单击它,否则它不会重新绘制时,您的基础数据是否发生了本应导致数据(渲染条)的视觉显示发生更改的情况 如果数据发生了更改,但表没有立即重新呈现,那么我会说您的TableModel工作不正常 基础数据更改->表格模型更改->激发表格模型事件->JTable重新呈现 查看TableModel tuturial:
为了确保您所做的一切都是正确的。出于性能原因,JTable重用渲染器组件来绘制多个单元格-因此,当您在JTable中看到组件时,它实际上并不在某个位置的容器中的组件的传统意义上。这意味着在渲染器组件上调用repaint()不会产生任何效果 最有效的选择是在TableModel中存储条的整数值。您的TableCellRenderer将如下所示:
public class BarTableCellRenderer implements TableCellRenderer {
private final BarRenderer rendererComponent = new BarRenderer(0, 10);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
rendererComponent.setXval((Integer)value);
return rendererComponent;
}
}
然后您可以更改TableModel中的整数,它将触发条的重新绘制(您可能需要TableModel.fireTableCellUpdated,具体取决于您使用的TableModel实现).出于性能原因,JTable重用渲染器组件来绘制多个单元格-因此,当您在JTable中看到组件时,它实际上并不在某个位置的容器中的组件的传统意义上。这意味着在渲染器组件上调用repaint()不会产生任何效果 最有效的选择是在TableModel中存储条的整数值。您的TableCellRenderer将如下所示:
public class BarTableCellRenderer implements TableCellRenderer {
private final BarRenderer rendererComponent = new BarRenderer(0, 10);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
rendererComponent.setXval((Integer)value);
return rendererComponent;
}
}
然后,您可以更改TableModel中的整数,它将触发条的重新绘制(您可能需要一个TableModel.fireTableCellUpdated,具体取决于您正在使用的TableModel实现)。在双方(Russ Hayward和Andrew)的帮助下,关键是执行以下操作:
- 将要使其可见的状态存储在TableModel本身中,而不是在渲染器中
- 确保当TableModel的状态更改时,调用
fireTableCellUpdated()
- 我的自定义列只有一个TableCellRenderer对象和一个JComponent(不是每个单元格一个)
- 在
TableCellRenderer.getTableCellRendererComponent()中存储单元格的状态,以便稍后进行渲染(长期存储在TableModel中)
- 向JComponent提供该状态
- 返回JComponent
- 重写
JComponent.PaintComponent()
- 在
- 一种方便的方法是自定义呈现程序扩展JComponent并实现TableCellRenderer,然后在
TableCellRenderer.getTableCellRenderComponent()中存储单元格的状态并
返回该状态代码>
class TraceControlTableModel extends AbstractTableModel {
/* handle table state here */
// convenience method for setting bar value (table model's column 2)
public void setBarValue(int row, double x)
{
setValueAt(x, row, 2);
}
}
// one instance of BarRenderer will be set as the
// TableCellRenderer for table column 2
public static class BarRenderer extends JComponent
implements TableCellRenderer
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
super();
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);
}
@Override
public Component getTableCellRendererComponent(JTable arg0,
Object value,
boolean isSelected, boolean hasFocus,
int row, int col)
{
// save state here prior to returning this object as a component
// to be painted
this.xval = (Double)value;
return this;
}
}
你们两位(Russ Hayward和Andrew)都提供了帮助,关键是要做到以下几点:
- 将要使其可见的状态存储在TableModel本身中,而不是在渲染器中
- 确保当TableModel的状态更改时,调用
fireTableCellUpdated()
- 我的自定义列只有一个TableCellRenderer对象和一个JComponent(不是每个单元格一个)
- 在
TableCellRenderer.getTableCellRendererComponent()中存储单元格的状态,以便稍后进行渲染(长期存储在TableModel中)
- 向JComponent提供该状态
- 返回JComponent
- 重写
JComponent.PaintComponent()
- 在
- 一种方便的方法是自定义呈现程序扩展JComponent并实现TableCellRenderer,然后在
TableCellRenderer.getTableCellRenderComponent()中存储单元格的状态并
返回该状态代码>
class TraceControlTableModel extends AbstractTableModel {
/* handle table state here */
// convenience method for setting bar value (table model's column 2)
public void setBarValue(int row, double x)
{
setValueAt(x, row, 2);
}
}
// one instance of BarRenderer will be set as the
// TableCellRenderer for table column 2
public static class BarRenderer extends JComponent
implements TableCellRenderer
{
final private double xmin;
final private double xmax;
private double xval;
public BarRenderer(double xmin, double xmax)
{
super();
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);
}
@Override
public Component getTableCellRendererComponent(JTable arg0,
Object value,
boolean isSelected, boolean hasFocus,
int row, int col)
{
// save state here prior to returning this object as a component
// to be painted
this.xval = (Double)value;
return this;
}
}
听起来是个可能的解决方案。。。我认为TableModel.fireTableCellUpdated听起来像是这里的关键。听起来像是一个可能的解决方案。。。我认为TableModel.fireTableCellUpdated听起来像是这里的关键。