如何创建一个Look& Feel感知TableCellRenderer?

时间:2014-12-01 10:22:30

标签: java swing look-and-feel tablecellrenderer uimanager

我可以找到自定义TableCellRenderer的所有示例都显示为DefaultTableCellRenderer。我猜,没错,除了你没有扩展当前外观和感觉的TableCellRenderer功能。这是不好的。那么你的TableCellRenderer并不是L& F意识。

这实际上就是我想要做的事情:我想创建一个L& F意识的自定义TableCellRenderer,所以不应该扩展DefaultTableCellRenderer它应该扩展(或装饰)任何东西L& F默认为给定的类类型安装的TableCellRenderer

我可以通过myJTable.getDefaultRenderer(...)来做到这一点,但这不会给我一个新课程的实例,它只会让L& F' master'表格单元格渲染器用于该类型的类。我开始创建一个自定义TableCellRenderer的解决方案,它包装了我从上述方法中获得的实例(实际上使用了Decorator模式),直到我意识到我没有自己的渲染器私有实例。如果我弄乱了渲染器的这个实例,我不能进行特定于列的渲染,因为我在该实例上所做的任何更改都会影响比预期更多的列。

所以我得出结论,我需要做的是为该类型创建一个全新的L& F TableCellRenderer实例。 (在我的例子中类类型= Object)。我相信我可以从UIManager的某处找到相关的班级名称,但我不知道要使用哪个键。其次 - 不幸的是 - 我相信我必须使用Reflection实际实例化该TableCellRenderer类的对象。

我的假设是否正确,即不幸的是没有TableCellRenderers的工厂?以及如何为类型TableCellRenderer实际实例化当前L& F Object的新实例? (我知道如何使用Reflection,如果这是唯一的方法)

更新

您可能已经猜到我使用专有的L& F以及标准的L& F进行测试。这个特别的专有L& F安装了自己的TableCellRenderers,这是完全合法的IMO。 Java Synth L& F也是如此。所以我不想让这个问题成为一个特定的L& F.

测试:我创建了一个包含两个String列的表。我在其中一列上安装了自己的自定义单元格渲染器,但没有在另一列上安装。我的自定义渲染器如下所示:

public class CustomCellRenderer extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(
              JTable table, Object value, boolean isSelected, boolean hasFocus,
              int row, int column) {
        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    }
}

如您所见,自定义渲染器不执行任何操作。由于它什么都不做,我应该在两个表列上获得相同的渲染效果。我不是!原因当然是简单地延长DefaultTableCellRenderer我不会继承' L& F自己的TableCellRenderers应该有一个/一个。在很多很多L& F上面,上述测试实际上会以相同的方式呈现两列,但这更偶然。我想以正确的方式做事。扩展DefaultTableCellRenderer产生大多数L& Fs的预期结果这一事实对我来说还不够。 : - )

2 个答案:

答案 0 :(得分:1)

  

我的假设是否正确,即不幸的是没有工厂   TableCellRenderers?我将如何实际实例化一个新的   类型对象的当前L& F的TableCellRenderer的实例?   (我知道如何使用Reflection,如果这是唯一的方法)

我会说你的假​​设是关闭的,例如,以下屏幕截图使用完全相同的代码用于Cross平台/金属,系统/ MacOS和Nimbus(Synth)。

Meta/CrossPlatform System/MacOS Nimbus

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class Test101 {

    public static void main(String[] args) {
        new Test101();
    }

    public Test101() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
//                  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//                  UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                    UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DefaultTableModel model = new DefaultTableModel();
                for (int index = 0; index < 10; index++) {
                    model.addColumn(Character.toString((char)('A' + index)));
                }

                for (int row = 0; row < 10; row++) {
                    Vector rowData = new Vector(10);
                    for (int col = 0; col < 10; col++) {
                        rowData.add(row + "x" + col);
                    }
                    model.addRow(rowData);
                }

                JTable table = new JTable(model);
                table.setDefaultRenderer(String.class, new DefaultTableCellRenderer());
                table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer());
                // Just so you don't tell me that the lookup doens't work
                table.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

如果您从AbstractTableCellRendererDefaultTableCellRenderer延伸,则应使用JTable及其属性(字体,颜色等)或UIManager属性{} {{ 1}}没有为您提供所需的信息。

  

所以我得出结论,我需要做的是创造一个全新的   该类型的L&amp; F的TableCellRenderer的实例。 (在我的   case class type = Object)。我相信我可以上相关课程   从UIManager的某个地方命名,但我不知道哪个键   使用。其次 - 不幸的是 - 我相信我必须使用   实际实例化该TableCellRenderer的对象的反射   类。

如果您真的打算创建自己的外观,那么您只需要这样做。每天提供您自己的JTable,这是根据提供的TableCellRenderer的属性配置的,并且在极少数情况下,修改JTable中存在的属性应该足够......

答案 1 :(得分:0)

我们这样解决了这个问题:

public class CustomCellRenderer  implements TableCellRenderer {
    //Use appropriate class here
    private final TableCellRenderer defaultTableCellRenderer= new JTable().getDefaultRenderer(Object.class);
    @Override
    public Component getTableCellRendererComponent(
              JTable table, Object value, boolean isSelected, boolean hasFocus,
              int row, int column) {
        Component c = defaultTableCellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        // do custom stuff to c here ...
        return c;
    }
}

如果您没有为TableCellRenderer创建新实例,则可以获得时髦的效果,因为您更改了表的默认实例。