java - 如何用图形相关指令装饰TableCellRenderer?

标签 java swing user-interface jtable rendering

我正在使用装饰器设计模式实现TableCellRenderer。 只要我需要以可以在 getTableCellRendererComponent(..) 范围内执行的方式装饰从装饰渲染器返回的组件,一切都可以很好地工作。
但是,对于在绘制过程中需要 Graphics 对象的情况,如何装饰返回的组件呢?特别是 - 在他的 paintComponent(Graphics g) 方法中?
例如,当我想绘制某条线时,简单的 setBorder(..) 是不够的:

import java.awt.Color;
import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.DefaultTableCellRenderer;


public class MyTableCellRendererDecorator extends DefaultTableCellRenderer {

    private TableCellRenderer decoratedRenderer;
    private Component decoratedComponent;

    public MyTableCellRendererDecorator(TableCellRenderer decoratedRenderer) {
        super();
        this.decoratedRenderer = decoratedRenderer;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {

        this.decoratedComponent = decoratedRenderer.getTableCellRendererComponent(table, value,
            isSelected, hasFocus, row, column);

        //an example for a decoration which works fine
        decoratedComponent.setBackground(Color.red);

        return decoratedComponent;
    }

    /**
     * This code will NOT be executed, because the paint will be called on the returned component
     * from getTableCellRendererComponent() and NOT on this JLabel in which this renderer subclasses.
     */
    @Override
    public void paintComponent(Graphics g) {
        decoratedComponent.paint(g);
        //an example for a needed decoration in paintComponent()
        Rectangle bounds = g.getClipBounds();
        g.setColor(Color.BLUE);
        g.drawLine(0, 0, bounds.width, bounds.height);
    }
}

我想到了两种不同的解决方案:
1.引入一个名为DecolatedTableCellRenderer的接口(interface):

import javax.swing.table.TableCellRenderer;

public interface DecoratedTableCellRenderer extends TableCellRenderer {

    public void setPostPaintComponentRunnable(Runnable postPaintComponentRunnable);
}

现在,MyTableCellRendererDecorator 将在其构造函数中收到一个 DecolatedTableCellRenderer,而不是一个简单的 TableCellRenderer,并且负责在 paintComponent 内部进行装饰 移动到装饰类。如果我们假设渲染器是一个可以自行绘制的 JComponent ,则可以通过重写 paintComponent(..) 并应用 postPaintComponentRunnable.run() 来完成> 在他自己的绘制代码之后。
但是,如果我想支持此类装饰渲染器,并将其应用于我可能无法修改的任何 TableCellRenderer 上,该怎么办?
2. 使用java的反射和动态代理实例化一个新的ComponentUI委托(delegate)给decoratedComponent,它将作为其原始ComponentUI对象执行每个方法,仅使用 paint(Graphics g, JComponent c) 的修饰版本。
这会将装饰责任保留在装饰类中,但在我看来,动态代理总是有点难以阅读和维护,如果我能找到一个更优雅的想法,我将非常高兴。

最佳答案

事实证明,您提供的原始示例代码接近正确,因为实际上返回的组件是 this。也就是说,getTableCellRendererComponent 返回调用它的 DefaultTableCellRenderer,因此在绘制组件期间将调用 DefaultTableCellRenderer 子类中的任何重写方法。

下面是 DefaultTableCellRenderer 的代码,它显示了我正在讨论的内容:

public Component getTableCellRendererComponent(JTable table, Object value,
                      boolean isSelected, boolean hasFocus, int row, int column) {
    //...
    return this;
}

因此,如果您重写 paint(Graphics gfx) 方法并调用您的父类(super class) getTableCellRendererComponent,您将能够在单元格中绘制您想要的任何内容。

因此,您的 getTableCellRendererComponent 应如下所示:

@Override
public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {

    JLabel component = super.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);

    //an example for a decoration which works fine
    component.setBackground(Color.red);

    return component;
}

并在 DefaultTableCellRenderer 的子类中使用 paint 方法,而不是像这样的 paintComponent :

/**
 * This code WILL be executed.
 */
@Override
public void paint(Graphics g) {
    super.paint(g);
    //an example for a needed decoration in paintComponent()
    Rectangle bounds = g.getClipBounds();
    g.setColor(Color.BLUE);
    g.drawLine(0, 0, bounds.width, bounds.height);
}

关于java - 如何用图形相关指令装饰TableCellRenderer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23305319/

相关文章:

Swift - 解析 - friend 列表 - 可以创建 friend 组

android - Titanium:当布局=垂直时隐藏 View

java - 在Java中通过反射获取私有(private)字段

matlab - MATLAB GUI 中的全局变量?

java - 如何使用 java 驱动程序使用两个 "where"条件更新 MongoDB 中的数组项

Java 操作监听器和 JButton

java - 如何使用 Canvas 根据用户输入绘制多个矩形?

java - 使用工作线程时返回语句

java - 通过线程名称或线程组名称终止线程 - Java

java - 组合锁 (Java)