在JTable中显示组件的最佳方法?

时间:2012-02-16 14:28:23

标签: java swing jtable jcomponent performance

我不是要问如何在JTable中显示Component,因为在线有几个教程和示例。但是,我想知道最好的解决方法是什么。

例如,我遇到的大多数教程都有一些示例可以创建单独的类(Main类,一个扩展JTable,扩展TableModel,扩展TableCellRenderer,等等。 )。但是,我发现你不仅可以在一个类中完成它,而且可以通过简单地使用以下方法来实现:

示例代码(SSCCE)


主要

public class Main
{
  public static void main(String[] args)
  {
    javax.swing.JFrame jf = new javax.swing.JFrame("A table with components");
    jf.setLayout(new java.awt.BorderLayout());
    jf.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    jf.add(new TableWithCompsPanel(), java.awt.BorderLayout.CENTER);
    jf.setVisible(true);
  }
}

TableWithComps

public class TableWithCompsPanel extends java.awt.Container
{
  private Class<?> tableColumnClassArray[];
  private javax.swing.JTable jTableWithComps;
  private Object tableContentsArray[][];

  public TableWithCompsPanel()
  {
    tableContentsArray = new Object[][]
      {
        {"This is plain text",                                            new javax.swing.JButton("This is a button")    },
        {new javax.swing.JLabel("This is an improperly rendered label!"), new javax.swing.JCheckBox("This is a checkbox")}
      };
    tableColumnClassArray = new Class<?>[]{String.class, java.awt.Component.class};
    initGUI();
  }

  private void initGUI()
  {
    setLayout(new java.awt.BorderLayout());
    jTableWithComps = new javax.swing.JTable(new javax.swing.table.AbstractTableModel()
      {
        @Override public int getRowCount()
        {
          return tableContentsArray.length;
        }

        @Override public int getColumnCount()
        {
          return tableContentsArray[0].length;
        }

        @Override public Object getValueAt(int rowIndex, int columnIndex)
        {
          return tableContentsArray[rowIndex][columnIndex];
        }

        @Override public Class<?> getColumnClass(int columnIndex)
        {
          return tableColumnClassArray[columnIndex];
        }
      });
    jTableWithComps.setDefaultRenderer(java.awt.Component.class, new javax.swing.table.TableCellRenderer()
    {
      @Override public java.awt.Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
      {
        return value instanceof java.awt.Component ? (java.awt.Component)value : new javax.swing.table.DefaultTableCellRenderer();
      }
    });
    add(jTableWithComps, java.awt.BorderLayout.CENTER);
  }
}

问题


我想知道的是,如果可以在如此短的代码中完成,为什么示例会将它们分成三个,有时甚至更多的类?我的代码在运行时是否效率较低?我可以理解将主类和具有示例GUI的类分开,但不是为什么要将示例GUI分成几个类。

编辑:我看到很多人都说明了为什么这段代码不切实际的原因。如果您提供替代方案,我将非常感谢您的回答!

4 个答案:

答案 0 :(得分:5)

为了提高内存效率,TableModel以最简单的方式为您要跟踪的数据建模。 TableCellRenderer定义了如何在表格单元格中显示该数据。

在iTunes复选框示例中,从复选框中建模信息的最简单方法是布尔值(true / false)。存储10,000个boolean个对象而不是10,000个JCheckBox个对象的内存效率要高得多。

然后TableCellRenderer可以存储单个JCheckBox对象,当要求用于绘制单元格的组件时,它可以根据值检查/取消选中复选框并返回每次都是相同的组件。这样,当用户滚动表格时,您不会一遍又一遍地创建数千个UI组件。

答案 1 :(得分:3)

一般来说,这么多组件交互的划分是因为设计。这种设计试图运用良好的原则,如关注点的分离。您可以构建一个可以完成所有任务的大事,或者通过其责任来识别每个部件的较小部件。在后一种情况下,您的代码更适合更改,因为每个类只执行一项操作并且更改大量时间意味着在不破坏解决方案的一般体系结构的情况下触及一个或两个责任。

特别是Swing应用的MVC模式有点冗长,但试图掌握很多优秀的设计原则。我知道维护并不总是最简单的事情,但我必须认识到责任是非常分离的。

样品可能很短。但他们必须坚持Swing的哲学和架构。这就是为什么他们独立于代码的大小实现相同的角色。

对此(恕我直言)的经验法则是为每个部门找出分割的原因。

性能:如果您的代码分成几个类,请不要担心。它不会影响性能。其他的事情(如时间复杂性)确实如此。或者可能是组件使用不当,但是如果所有组件都按照预期使用那么事情会没事的。

编辑:希望这个答案有用!正如你所看到的那样,它根本不是摆动的......

答案 2 :(得分:2)

要考虑的事情:

  • 从您的示例中看,单元格值是一个Component。这不会为每个非平凡的桌子占用大量内存吗?
  • 如果选择了行,焦点等,组件是否正确绘制?
  • 除非您的组件非常智能,否则您可能无法使单元格可编辑。

答案 3 :(得分:1)

  1. Renderer仅用于在视觉上装饰细胞的内容,例如setFont,setForeground,setBackground,isEnable,isVisible等。

  2. 请勿在运行时在JComponents中创建,设置,更改Renderer类型;这是TableModel的工作。

  3. 如果可以,请使用DefaultTableModel并利用types known to JTable的现有渲染器。

  4. 您知道Object/JComponent的单元格中存在JTable {{1}}个{。}}