使用 setValueAt 重新创建互斥复选框 [英] Using setValueAt to recreate mutually exclusive check boxes

查看:23
本文介绍了使用 setValueAt 重新创建互斥复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用自定义 DefaultTableModel 的 JTable,它在最后一列中有一些布尔值(显示为复选框).

I have a JTable using a custom DefaultTableModel which has some Booleans in the last column (displayed as tick boxes).

当我添加一个 MouseListener 来检索被点击的值时,似乎不再发生勾选框的切换.

When I add a MouseListener to retrieve the value of what's been clicked it appears that the toggling of tick boxes no longer takes place.

// As soon as this is used in the component
// that is using the JTable, the toggling stops
table.addMouseListener(new MouseAdapter() {  
            public void mouseClicked(MouseEvent evt) {  
                int col = table.getSelectedColumn();  
                int row = table.getSelectedRow();

                Object o = table.getModel().getValueAt(row, col);

我假设该事件正在被侦听器消耗.我可以在 MouseListener 代码中添加什么来恢复切换行为?

I assume that the event is being consumed by the listener. What can I add to the MouseListener code to restore the toggling behaviour?

糟糕,问题似乎出在我的覆盖上:

Oops, it appears that the issue lies with my override:

@Override
public void setValueAt(Object aValue, int row, int column) {

    // Attempt at mutually exclusive checkboxes
    if( column == 2 ){ // Starts at 0. Seek an alternative solution to avoid hardcoding?
        // Algorithm: cycle through List to set other Booleans to false

        // Uses entities. Is there another way of getting the number of rows from model?
        List<MyEntity> myEntities = this.getDatas();

        for( int i = 0; i < myEntities.size(); i++ ){
            if( i != row ){
                // Make sure this calls parent
                super.setValueAt( false , i, 2);
            }
        }

    } else {
        super.setValueAt(aValue, row, column); // Call parent class
    }

}  

推荐答案

不要添加自己的 MouseListener.而是覆盖 TableModel 中的 setValueAt() 以查看默认编辑器为 Boolean.class 设置的新值.

Don't add your own MouseListener. Instead override setValueAt() in the TableModel to see the new value set by the default editor for Boolean.class.

附录:这是一个 sscce.为方便起见,它只是清除 CHECK_COL 中的所有条目,设置新值并相应地调节按钮.

Addendum: Here's an sscce. For expedience, it simply clears all entries in CHECK_COL, sets the new value and conditions the button accordingly.

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

/**
 * @see http://stackoverflow.com/questions/7920068
 * @see http://stackoverflow.com/questions/4526779
 */
public class CheckOne extends JPanel {

    private static final int CHECK_COL = 1;
    private static final Object[][] DATA = {
        {"One", Boolean.FALSE}, {"Two", Boolean.FALSE},
        {"Three", Boolean.FALSE}, {"Four", Boolean.FALSE},
        {"Five", Boolean.FALSE}, {"Six", Boolean.FALSE},
        {"Seven", Boolean.FALSE}, {"Eight", Boolean.FALSE},
        {"Nine", Boolean.FALSE}, {"Ten", Boolean.FALSE}};
    private static final String[] COLUMNS = {"Number", "CheckBox"};
    private DataModel dataModel = new DataModel(DATA, COLUMNS);
    private JTable table = new JTable(dataModel);
    private ControlPanel cp = new ControlPanel();

    public CheckOne() {
        super(new BorderLayout());
        this.add(new JScrollPane(table));
        this.add(cp, BorderLayout.SOUTH);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.setPreferredScrollableViewportSize(new Dimension(250, 175));
    }

    private class DataModel extends DefaultTableModel {

        public DataModel(Object[][] data, Object[] columnNames) {
            super(data, columnNames);
        }

        @Override
        public void setValueAt(Object aValue, int row, int col) {
            if (col == CHECK_COL) {
                for (int r = 0; r < getRowCount(); r++) {
                    super.setValueAt(false, r, CHECK_COL);
                }
            }
            super.setValueAt(aValue, row, col);
            cp.button.setEnabled(any());
        }

        private boolean any() {
            boolean result = false;
            for (int r = 0; r < getRowCount(); r++) {
                Boolean b = (Boolean) getValueAt(r, CHECK_COL);
                result |= b;
            }
            return result;
        }

        @Override
        public Class<?> getColumnClass(int col) {
            if (col == CHECK_COL) {
                return getValueAt(0, CHECK_COL).getClass();
            }
            return super.getColumnClass(col);
        }

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

    private class ControlPanel extends JPanel {

        JButton button = new JButton("Button");

        public ControlPanel() {
            button.setEnabled(false);
            this.add(new JLabel("Selection:"));
            this.add(button);
        }
    }

    private static void createAndShowUI() {
        JFrame frame = new JFrame("CheckOne");
        frame.add(new CheckOne());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

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

这篇关于使用 setValueAt 重新创建互斥复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆