2

我想实现一个作为选项列表的组件,用户可以选择或不选择。
在视觉上我认为它最好在 UI 中呈现(如果有更好的方法请告诉我)如下:
在此处输入图像描述

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

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 );
    }

发生的情况是,当框架出现时,我在表中看到“测试”,但它不像复选框(如示例图像中所示)。
如果我单击单元格,它会变成一个复选框(单击左侧而不是右侧的按钮),但文本会更改为显示truefalse!它不会一直
在文本上显示“测试”更多取决于我是否继续按下单元格。
如果我将其更改JCheckBox为 a JComboBox,则据我所知,该行为是正确的。
谁能告诉我我在这里做错了什么?
谢谢!

4

2 回答 2

2

默认JCheckBox呈现为 a ,表的模型必须作为该列的类型返回。如果您正在使用,则必须相应地覆盖。这是一个相关的例子Boolean.classDefaultTableModelgetColumnClass()

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

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

setValueAt()无论如何都被调用。通过调试验证它

如果您进入setValueAt(),您将看到“提供了这个空实现,因此如果他们的数据模型不可编辑,用户不必实现此方法”。

于 2011-07-09T07:43:47.333 回答
2

在这里您可以找到答案,为什么 (JButtons JComponents) JCheckBox 和 JRadioButton ... 对于在 TableCell 中作为另一个 JComponents 进行渲染有点不同(并且您必须使用 JTable 行选择,因为我更改了不透明度)

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&F(需要 Java > 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 "-";
        }
    }
}
于 2011-07-09T08:07:49.703 回答