关于jtable细胞编辑的问题

时间:2011-07-09 07:37:50

标签: java swing user-interface jtable jcheckbox

我想实现一个用作选项列表的组件,用户可以选择是否选择 在视觉上我认为它最好在UI中呈现(如果有更好的方法,请告诉我)如下:
enter image description here

无论如何,我认为这可以通过JTable(单列)并使用JCheckBox作为单元格编辑器来实现。
我尝试了但是没有用。
代码示例:

public class ListRenderer extends JFrame {

    JCheckBox checkbox = new JCheckBox("Test");
    DefaultCellEditor dce1 = new DefaultCellEditor(checkbox);

    public ListRenderer(){          

        Object[][] data =  {   {"Test"} };
        String[] columnNames = {"Options"};

        DefaultTableModel model = new DefaultTableModel(data,columnNames);

        JTable table = new JTable(model){

            public TableCellEditor getCellEditor(int row, int column)            
            {               
                return dce1;                
            }

        };
        JScrollPane scrollPane = new JScrollPane( table );        
        getContentPane().add( scrollPane );
    }

当框架出现时,我看到表格中的“测试”,但它看起来不像一个复选框(如示例图片中所示)。
如果我单击单元格,它会变成一个复选框(左侧单击按钮而不是右侧),但文本更改为显示 true false !它没有继续显示“测试”
更多文字取决于我是否继续按下牢房 如果我将JCheckBox更改为JComboBox,就我所知,行为是正确的 任何人都可以告诉我,我在这里做错了什么? 谢谢!

2 个答案:

答案 0 :(得分:2)

要按default呈现为JCheckBox,表格的模型必须返回Boolean.class作为该列的类型。如果您使用的是DefaultTableModel,则必须相应地覆盖getColumnClass()。这是一个相关的example

附录:请注意example编辑的ValueRenderer私有实例可以直接应用ItemEvent,而不是setValueAt()

附录:example已更新,以反映正确的模型 - 视图工作流程。

  无论如何,

setValueAt()被召唤。通过调试验证

如果您进入setValueAt(),您会看到“此空实现已提供,因此如果用户的数据模型不可编辑,则不必实施此方法。”

答案 1 :(得分:2)

在这里你可以找到答案为什么(JButtons JComponents)JCheckBox和JRadioButton ...在TableCell中作为另一个JComponents渲染有点不同(你必须使用JTable行选择,因为我改变了Opacity)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class CheckboxInCellTest {

    private String[] columnNames = {"Boolean(Default)", "Boolean"};
    private Object[][] data = {{false, true}, {true, false}, {false, true}};
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) {

        private static final long serialVersionUID = 1L;

        @Override
        public Class<?> getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };

    public JComponent makeUI() {
        JTable table = new JTable(model);
        table.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                JTable t = (JTable) e.getComponent();
                Point pt = e.getPoint();
                int row = t.rowAtPoint(pt), col = t.columnAtPoint(pt);
                if (t.convertColumnIndexToModel(col) == 1) {
                    t.getCellEditor(row, col).stopCellEditing();
                }
            }
        });
        table.setRowHeight(20);
        CheckBoxEditorRenderer1 cer = new CheckBoxEditorRenderer1();
        table.getColumnModel().getColumn(1).setCellRenderer(cer);
        table.getColumnModel().getColumn(1).setCellEditor(cer);
        JPanel p = new JPanel(new BorderLayout());
        p.add(new JScrollPane(table));
        return p;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new CheckboxInCellTest().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class CheckBoxPanel1 extends JPanel {

    private static final long serialVersionUID = 1L;
    public final JCheckBox button = new JCheckBox();

    CheckBoxPanel1() {
        super(new GridBagLayout());
        add(button);
        button.setOpaque(false);
        setOpaque(false);
    }
}

class CheckBoxEditorRenderer1 extends AbstractCellEditor implements TableCellRenderer, TableCellEditor {

    private static final long serialVersionUID = 1L;
    private final CheckBoxPanel1 editor = new CheckBoxPanel1();
    private final CheckBoxPanel1 renderer = new CheckBoxPanel1();

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean is, boolean hf, int row, int column) {
        renderer.button.setSelected(Boolean.TRUE.equals(value));
        renderer.button.setOpaque(is);
        return renderer;
    }

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

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

和TableCell中的JButton ...与Nimbus L&amp; F(需要Java&gt; 1.6.17 ???现在我有xxx.25)

import com.sun.java.swing.Painter;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.util.LinkedList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import sun.swing.table.DefaultTableCellHeaderRenderer;

public class TableButtonTest extends JFrame {

    private static final long serialVersionUID = 1L;

    public TableButtonTest() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTable table = new JTable(new TestModel());
        table.getTableHeader().setReorderingAllowed(false);
        table.setRowHeight(20);
        table.getColumnModel().getColumn(1).setPreferredWidth(3);
        table.getColumnModel().getColumn(2).setPreferredWidth(3);
        table.getTableHeader().setDefaultRenderer(new WrappingRenderer(table.getTableHeader()));
        this.add(new JScrollPane(table));
        Action increase = new AbstractAction("+") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                JTable table = (JTable) e.getSource();
                int row = Integer.valueOf(e.getActionCommand());
                TestModel model = (TestModel) table.getModel();
                model.increment(row, 0);
                //model.fireTableCellUpdated(row, 0);
            }
        };
        ButtonColumn inc = new ButtonColumn(table, increase, 1);
        Action decrease = new AbstractAction("-") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                JTable table = (JTable) e.getSource();
                int row = Integer.valueOf(e.getActionCommand());
                TestModel model = (TestModel) table.getModel();
                model.decrement(row, 0);
            }
        };
        ButtonColumn dec = new ButtonColumn(table, decrease, 2);
        JTableHeader tbh = table.getTableHeader();
        tbh.setOpaque(false);
        Painter painter = new com.sun.java.swing.Painter() {

            public void paint(Graphics2D g, Object o, int w, int h) {
            }
        };
        javax.swing.UIDefaults defaults = new javax.swing.UIDefaults();
        defaults.put("TableHeader:\"TableHeader.renderer\"[Pressed].backgroundPainter", painter);
        defaults.put("TableHeader:\"TableHeader.renderer\"[Pressed].backgroundPainter",
                defaults.get(("TableHeader:\"TableHeader.renderer\"[Pressed].backgroundPainter")));
        tbh.putClientProperty("Nimbus.Overrides", defaults);
        tbh.putClientProperty("Nimbus.State", "Pressed");
        tbh.putClientProperty("JTree.lineStyle", "Angled");
        setLocation(200, 200);
        pack();
    }

    private static class WrappingRenderer implements TableCellRenderer {

        private DefaultTableCellHeaderRenderer delegate;
        private JTableHeader header;

        public WrappingRenderer(JTableHeader header) {
            this.header = header;
            this.delegate = (DefaultTableCellHeaderRenderer) header.getDefaultRenderer();
            header.setDefaultRenderer(this);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component comp = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            TableColumn draggedColumn = table.getTableHeader().getDraggedColumn();
            if (isSelected) {
                comp.setBackground(table.getSelectionBackground());
            } else {
                comp.setBackground(table.getBackground());
            }

            if (draggedColumn != null) {
                if (table.convertColumnIndexToModel(column) == draggedColumn.getModelIndex()) {
                    setNimbusState("Pressed");
                } else {
                    setNimbusState(null);
                }
            } else {
                setNimbusState(null);
            }
            // do similar for resizing column
            return comp;
        }

        public void setNimbusState(String state) {
            delegate.putClientProperty("Nimbus.State", state);
        }
    }

    public static void main(String[] args) {
        try {
            // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if (info.getName().equals("Nimbus")) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        new TableButtonTest().setVisible(true);
    }
}

class TestModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;
    private List<TestRecord> records = new LinkedList<TestRecord>();

    private static class TestRecord {

        private int val = 0;
    }

    public void increment(int row, int col) {
        records.get(row).val++;
        fireTableCellUpdated(row, col);
    }

    public void decrement(int row, int col) {
        records.get(row).val--;
        fireTableCellUpdated(row, col);
    }

    public TestModel() {
        records.add(new TestRecord());
        records.add(new TestRecord());
    }

    @Override
    public Class<?> getColumnClass(int col) {
        switch (col) {
            case 0:
                return Integer.class;
            case 1:
                return ButtonColumn.class;
            case 2:
                return Boolean.class;
            default:
                return String.class;
        }
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        return true;
    }

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

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

    @Override
    public Object getValueAt(int row, int col) {
        if (col == 0) {
            return records.get(row).val;
        } else if (col == 1) {
            return "+";
        } else {
            return "-";
        }
    }
}