【问题标题】:Adding jRadioButton into jTable将 jRadioButton 添加到 jTable
【发布时间】:2012-06-30 20:31:01
【问题描述】:

我正在尝试将jRadioButton 添加到jTable。我使用了给定的代码

 private class CustomCellRenderer extends DefaultTableCellRenderer {

  /* (non-Javadoc)
   * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
   */

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


    return new javax.swing.JRadioButton();
  }

 }

但是当我运行这个时,我得到了不同颜色的jTable 列,当我点击单选按钮时没有任何反应。我正在使用netbeans。如果我尝试自定义jTable,那么jTable 中将不会出现任何内容。给我一个正确的指导。

【问题讨论】:

  • 另见example
  • @Trashgod:但在其他一些示例中,我还看到 RadioButton 的分组在 jTable 的情况下不起作用?
  • @mKorbel 的example 使用JPanel 来包含按钮组;在第二个附录here 中讨论了单独的列,以回应您关于此主题的previous question

标签: java swing netbeans jtable jradiobutton


【解决方案1】:
  1. 如果要编辑表格单元格的值,必须设置TableCellEditor
  2. 您应该在渲染器中创建一个 JRadioButton 并在任何地方重复使用它,这就是 TableCellRenderer 的目的。
  3. 如果不调用super.getTableCellRendererComponent,则不需要扩展DefaultTableCellRenderer,只需实现TableCellRenderer即可。

考虑阅读JTable tutorial 以更好地理解渲染器和编辑器的概念。

编辑:

这里有一个示例,说明如何使这项工作发挥作用。当然,你必须适应你的模型,但你应该明白要点:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class TestTable {

    public class RadioButtonCellEditorRenderer extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener {

        private JRadioButton radioButton;

        public RadioButtonCellEditorRenderer() {
            this.radioButton = new JRadioButton();
            radioButton.addActionListener(this);
            radioButton.setOpaque(false);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            radioButton.setSelected(Boolean.TRUE.equals(value));
            return radioButton;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            radioButton.setSelected(Boolean.TRUE.equals(value));
            return radioButton;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            stopCellEditing();
        }

        @Override
        public Object getCellEditorValue() {
            return radioButton.isSelected();
        }

    }

    private JFrame f;
    private JTable table;

    private class MyObjectManager {
        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
        private List<MyObject> objects = new ArrayList<TestTable.MyObject>();

        public void addObject(MyObject object) {
            objects.add(object);
            object.setManager(this);
            propertyChangeSupport.firePropertyChange("objects", null, object);
        }

        public List<MyObject> getObjects() {
            return objects;
        }

        public void setAsSelected(MyObject myObject) {
            for (MyObject o : objects) {
                o.setSelected(myObject == o);
            }
        }
    }

    private class MyObject {
        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

        private MyObjectManager manager;

        private String value;

        private boolean selected;

        public MyObject(String value) {
            this.value = value;
        }

        public PropertyChangeSupport getPropertyChangeSupport() {
            return propertyChangeSupport;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
            propertyChangeSupport.firePropertyChange("value", null, value);
        }

        public MyObjectManager getManager() {
            return manager;
        }

        public void setManager(MyObjectManager manager) {
            this.manager = manager;
            propertyChangeSupport.firePropertyChange("manager", null, manager);
        }

        public boolean isSelected() {
            return selected;
        }

        public void setSelected(boolean selected) {
            if (this.selected != selected) {
                this.selected = selected;
                if (selected) {
                    manager.setAsSelected(this);
                }
                propertyChangeSupport.firePropertyChange("selected", !selected, selected);
            }
        }

    }

    protected void initUI() {
        MyObjectManager manager = new MyObjectManager();
        for (int i = 0; i < 200; i++) {
            MyObject object = new MyObject("Row " + (i + 1));
            manager.addObject(object);
        }
        table = new JTable(new MyTableModel(manager));
        table.setRowHeight(20);
        TableColumn column = table.getColumnModel().getColumn(1);
        column.setCellEditor(new RadioButtonCellEditorRenderer());
        column.setCellRenderer(new RadioButtonCellEditorRenderer());
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new JScrollPane(table), BorderLayout.CENTER);
        f.pack();
        f.setVisible(true);

    }

    public class MyTableModel extends AbstractTableModel implements PropertyChangeListener {

        private final MyObjectManager manager;

        public MyTableModel(MyObjectManager manager) {
            super();
            this.manager = manager;
            manager.propertyChangeSupport.addPropertyChangeListener(this);
            for (MyObject object : manager.getObjects()) {
                object.getPropertyChangeSupport().addPropertyChangeListener(this);
            }
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getSource() == manager) {
                // OK, not the cleanest thing, just to get the gist of it.
                if (evt.getPropertyName().equals("objects")) {
                    ((MyObject) evt.getNewValue()).getPropertyChangeSupport().addPropertyChangeListener(this);
                }
                fireTableDataChanged();
            } else if (evt.getSource() instanceof MyObject) {
                int index = manager.getObjects().indexOf(evt.getSource());
                fireTableRowsUpdated(index, index);
            }
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public int getRowCount() {
            return manager.getObjects().size();
        }

        public MyObject getValueAt(int row) {
            return manager.getObjects().get(row);
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            switch (columnIndex) {
            case 0:
                return getValueAt(rowIndex).getValue();
            case 1:
                return getValueAt(rowIndex).isSelected();
            }
            return null;
        }

        @Override
        public void setValueAt(Object value, int rowIndex, int columnIndex) {
            if (columnIndex == 1) {
                getValueAt(rowIndex).setSelected(Boolean.TRUE.equals(value));
            }
        }

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

        @Override
        public Class<?> getColumnClass(int column) {
            switch (column) {
            case 0:
                return String.class;
            case 1:
                return Boolean.class;
            }
            return Object.class;
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
            case 0:
                return "Value";
            case 1:
                return "Selected";
            }
            return null;
        }

    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestTable().initUI();
            }
        });
    }

}

【讨论】:

  • @Tickua 我添加了一个我正在解释的例子。
  • @GuillaumePolet 我知道您并不打算将其作为一个完整的解决方案,但我仍然想提一点。如果您不从 DefaultTableCellRenderer 扩展,则需要小心寻找方法来指示单元格是否具有焦点、是否可编辑以及是否被选中。如果不这样做,那么这些单元格将与其他表格单元格的外观不匹配。
  • @Tickua 你说过你是初学者。对于初学者来说,这不是最容易尝试的任务,所以如果你遇到麻烦,不要感觉太糟糕!
  • @Enwired 正如 OP 提到的,他是初学者,我不想增加 SSCCE 的复杂性。如果他已经可以让他的代码工作,我们可以稍后修复背景/前景/边框以进行选择/聚焦。
  • 对于您发布的所有大量代码,令人震惊的是,很少有 cmets 伴随它来解释每个部分的作用。
【解决方案2】:
  1. 不建议在getTableCellRendererComponent 方法中返回新组件。相反,始终返回相同的组件,但根据值对其进行修改。这是可能的,因为返回的组件仅用作“标记”,而不是直接添加到 Swing 层次结构中。请参阅教程中的Renderers and Editors 部分
  2. 我在第一点中描述的内容解释了您无法单击按钮的原因。它只是表格中按钮的图像,而不是真正的按钮

另外,请考虑使用JCheckbox 而不是单选按钮。在这种情况下,当您的 TableModel 包含 boolean 值时,您可以简单地坚持使用默认渲染器/编辑器

【讨论】:

  • 我浏览了许多示例和您提供的链接。作为一名初学者,我完全糊涂了。在每个地方我都可以看到使用渲染器和编辑器的类。但是没有人描述我们怎么称呼它..我以正常方式尝试过(创建对象)然后它会出错..我在这里使用netbeans,其中已经定义了jTable的表模型..所以你能解释一下吗通过显示特定代码的简单方法??
  • 如果我尝试使用这个 new JRadioButton("a") 在 jTable 的自定义代码中添加单选按钮,那么它会变成 javax.swing.JRadioButton[,0,0, 0x0,invalid,alignmentX=0.0,.....text=a], 在列而不是按钮
猜你喜欢
  • 2012-06-25
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 2012-02-26
  • 1970-01-01
相关资源
最近更新 更多