【问题标题】:How to use custom JTable cell editor and cell renderer如何使用自定义 JTable 单元格编辑器和单元格渲染器
【发布时间】:2012-08-05 04:41:06
【问题描述】:

我创建了一个带有自定义表格渲染和自定义单元格编辑器的 JTable,它在图像中给出了结果

我使用扩展 JPanel 的单独类创建了第一个表格单元格中显示的面板。并将表值添加为,

        tbl.setCellEditor(new customCell());
        tbl.getColumnModel().getColumn(0).setCellRenderer(new customCell());

        DefaultTableModel dtm = (DefaultTableModel) tbl.getModel();

        Vector v = new Vector();
        v.add(new Panel());
        v.add("Test");
        dtm.addRow(v);

        v.clear();
        v.add(new Panel());
        v.add("Test 2");
        dtm.addRow(v);

这是我创建此表的表自定义类,

class customCell extends DefaultTableModel implements TableCellRenderer, TableCellEditor {

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Panel p = new Panel();            
            table.setRowHeight(row, p.getHeight());
            return p;
        }

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {

            return new Panel();
        }

        public Object getCellEditorValue() {
            return "";
        }

        public boolean isCellEditable(EventObject anEvent) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean shouldSelectCell(EventObject anEvent) {
            return true;
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        public boolean stopCellEditing() {
            return true;
        }

        public void cancelCellEditing() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void addCellEditorListener(CellEditorListener l) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void removeCellEditorListener(CellEditorListener l) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

我的问题是我认为面板按预期显示我无法在文本字段中输入或更改复选框或单击按钮。请告诉我如何解决这个问题。

【问题讨论】:

    标签: java swing jtable tablecellrenderer tablecelleditor


    【解决方案1】:

    我强烈建议重用默认表格渲染器和编辑器中提供的功能,因为您的代码有很多问题

    1. 请拆分您的编辑器、渲染器和表格模型。让他们都在同一个班级很奇怪
    2. 对于您的渲染器,不要每次都创建 Component 的新实例。相反,重用相同的组件,只需在 getTableCellRendererComponent 方法中修改 Component
    3. 编辑器Component 也是如此
    4. 扩展默认编辑器,而不是使用 UnsupportedOperationExceptions 或仅返回空的 Strings 来实现方法

    为了支持我的第四点,引用Editors part in the JTable tutorial:

    如果您想指定文本字段、复选框或组合框以外的编辑器怎么办?由于 DefaultCellEditor 不支持其他类型的组件,您必须多做一些工作。您需要创建一个实现 TableCellEditor 接口的类。 AbstractCellEditor 类是一个很好的超类。它实现了 TableCellEditor 的超接口 CellEditor,省去了实现单元格编辑器所需的事件触发代码的麻烦。

    您的单元格编辑器类至少需要定义两个方法——getCellEditorValue 和getTableCellEditorComponent。 CellEditor 所需的 getCellEditorValue 方法返回单元格的当前值。 TableCellEditor 所需的 getTableCellEditorComponent 方法应该配置并返回您要用作编辑器的组件。

    正如那里清楚解释的那样,您必须实现事件触发代码:

    为您省去实现单元格编辑器所需的事件触发代码的麻烦。

    你显然忽略了。因此我建议从AbstractCellEditor 开始,而不是从头开始实现接口

    【讨论】:

      【解决方案2】:

      必须为已经可见的JPanel 添加正确的LayoutManager、Editable/non_Editable 属性

      尽情享受

      import java.awt.*;
      import java.awt.event.*;
      import java.util.EventObject;
      import javax.swing.*;
      import javax.swing.table.*;
      
      public class PanelInTable {
      
          private JFrame frame;
          private JTable compTable = null;
          private PanelTableModel compModel = null;
          private JButton addButton = null;
      
          public static void main(String args[]) {
              try {
                  UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                  //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
              } catch (Exception fail) {
              }
              SwingUtilities.invokeLater(() -> {
                  new PanelInTable().makeUI();
              });
          }
      
          public void makeUI() {
              compTable = CreateCompTable();
              JScrollPane CompTableScrollpane = new JScrollPane(compTable, 
                      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
              JPanel bottomPanel = CreateBottomPanel();
              frame = new JFrame("Comp Table Test");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.add(CompTableScrollpane, BorderLayout.CENTER);
              frame.add(bottomPanel, BorderLayout.SOUTH);
              frame.setPreferredSize(new Dimension(800, 400));
              frame.setLocation(150, 150);
              frame.pack();
              frame.setVisible(true);
          }
      
          public JTable CreateCompTable() {
              compModel = new PanelTableModel();
              compModel.addRow();
              JTable table = new JTable(compModel);
              table.setRowHeight(new CompCellPanel().getPreferredSize().height);
              table.setTableHeader(null);
              PanelCellEditorRenderer PanelCellEditorRenderer = new PanelCellEditorRenderer();
              table.setDefaultRenderer(Object.class, PanelCellEditorRenderer);
              table.setDefaultEditor(Object.class, PanelCellEditorRenderer);
              return table;
          }
      
          public JPanel CreateBottomPanel() {
              addButton = new JButton("Add Comp");
              addButton.addActionListener(new ActionListener() {
      
                  @Override
                  public void actionPerformed(ActionEvent ae) {
                      Object source = ae.getSource();
                      if (source == addButton) {
                          compModel.addRow();
                      }
                  }
              });
              JPanel panel = new JPanel(new GridBagLayout());
              panel.add(addButton);
              return panel;
          }
      }
      
      class PanelCellEditorRenderer extends AbstractCellEditor implements 
              TableCellRenderer, TableCellEditor {
      
          private static final long serialVersionUID = 1L;
          private CompCellPanel renderer = new CompCellPanel();
          private CompCellPanel editor = new CompCellPanel();
      
          @Override
          public Component getTableCellRendererComponent(JTable table, Object value, 
                  boolean isSelected, boolean hasFocus, int row, int column) {
              renderer.setComp((Comp) value);
              return renderer;
          }
      
          @Override
          public Component getTableCellEditorComponent(JTable table, Object value, 
                  boolean isSelected, int row, int column) {
              editor.setComp((Comp) value);
              return editor;
          }
      
          @Override
          public Object getCellEditorValue() {
              return editor.getComp();
          }
      
          @Override
          public boolean isCellEditable(EventObject anEvent) {
              return true;
          }
      
          @Override
          public boolean shouldSelectCell(EventObject anEvent) {
              return false;
          }
      }
      
      class PanelTableModel extends DefaultTableModel {
      
          private static final long serialVersionUID = 1L;
      
          @Override
          public int getColumnCount() {
              return 1;
          }
      
          public void addRow() {
              super.addRow(new Object[]{new Comp(0, 0, "", "")});
          }
      }
      
      class Comp {
      
          public int type;
          public int relation;
          public String lower;
          public String upper;
      
          public Comp(int type, int relation, String lower, String upper) {
              this.type = type;
              this.relation = relation;
              this.lower = lower;
              this.upper = upper;
          }
      }
      
      class CompCellPanel extends JPanel {
      
          private static final long serialVersionUID = 1L;
          private JLabel labelWith = new JLabel("With ");
          private JComboBox typeCombo = new JComboBox(new Object[]
          {"height", "length", "volume"});
          private JComboBox relationCombo = new JComboBox(new Object[]
          {"above", "below", "between"});
          private JTextField lowerField = new JTextField();
          private JLabel labelAnd = new JLabel(" and ");
          private JTextField upperField = new JTextField();
          private JButton removeButton = new JButton("remove");
      
         public CompCellPanel() {
              setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
              relationCombo.addActionListener(new ActionListener() {
      
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      enableUpper(relationCombo.getSelectedIndex() == 2);
                  }
              });
              enableUpper(false);
              removeButton.addActionListener(new ActionListener() {
      
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      JTable table = (JTable) SwingUtilities.getAncestorOfClass(
                              JTable.class, (Component) e.getSource());
                      int row = table.getEditingRow();
                      table.getCellEditor().stopCellEditing();
                      ((DefaultTableModel) table.getModel()).removeRow(row);
                  }
              });
              add(labelWith);
              add(typeCombo);
              add(relationCombo);
              add(lowerField);
              add(labelAnd);
              add(upperField);
              add(Box.createHorizontalStrut(100));
              add(removeButton);
          }
      
          private void enableUpper(boolean enable) {
              labelAnd.setEnabled(enable);
              upperField.setEnabled(enable);
          }
      
          public void setComp(Comp Comp) {
              typeCombo.setSelectedIndex(Comp.type);
              relationCombo.setSelectedIndex(Comp.relation);
              lowerField.setText(Comp.lower);
              upperField.setText(Comp.upper);
              enableUpper(Comp.relation == 2);
          }
      
          public Comp getComp() {
              return new Comp(typeCombo.getSelectedIndex(), 
                      relationCombo.getSelectedIndex(), 
                      lowerField.getText(), upperField.getText());
          }
      }
      

      【讨论】:

      • 停止编辑属于编辑器,而不是面板。此外,从外部 actionListener 弄乱模型是……有争议的 ;-)
      • 感谢您的精彩捕捉,顺便说一句,您的诚实修改了此代码超过 3 次,我尝试移动并使用 Rob 制作的 JTable 中的 Action(我认为没有比这更好、更免费、更简单的了),没有任何更改和事件被触发,
      • 你为什么要扩展 AbstractCellEditor
      • @Radu Simionescu 因为....... 冰熊??? :-),我认为 SSCCE forn 中的代码示例最简单、紧凑,坚持公共论坛
      • 请使用小写的变量名,这很混乱。
      猜你喜欢
      • 2011-10-02
      • 2011-10-02
      • 2012-04-21
      • 2011-11-08
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      相关资源
      最近更新 更多