1

我对java很陌生,所以请原谅我犯的任何愚蠢的错误......

我有一个 2 列的 JTable,其中第 2 列可以有 4 种类型:

  • 不能更改值的列
  • 可以包含任何文本字符串的列
  • 包含 JComboBoxes 的列
  • 包含 JCheckBoxes 的列

列类型是动态的,因为它们取决于接收到的数据。

所有类型都可以正常工作,除了 JCheckBox。当我用具有 2 个选项的 JComboBox 替换 JCheckBox 时,它可以正常工作。所以我猜JCheckBox的代码有问题。

问题是 :

  • 当 JCheckBox 被选中时,我只需单击 1 次即可取消选中它
  • 但是,当未选中 JCheckBox 时,我需要单击它两次(而不是双击)来检查它

编辑

一个示例项目(尽可能小):

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

    public class frmCheck extends JApplet
    {
        JTable mgrdData;
        DefaultTableModel mtableModel;

        public void init()
        {
            mtableModel = new DefaultTableModel();
            mtableModel.setColumnCount(2);
            mtableModel.setRowCount(4);
            mgrdData = new JTable(mtableModel);
            mgrdData.getSelectionModel().addListSelectionListener(new RowListener());
            add(mgrdData);
            for (int i=1;i<mtableModel.getRowCount();i++)
            {
                addCheck(1);
            }
        }

        private class RowListener implements ListSelectionListener
        {
            public void valueChanged(ListSelectionEvent event)
            {
                if (event.getValueIsAdjusting()) return;
            }
        }

        private void addCheck(int intCol)
        {
            mgrdData.getColumnModel().getColumn(intCol).setCellRenderer(new TableCellRenderer()
            {
                public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean isFocused,int row,int col)
                {
                    JCheckBox rendererComponent = new JCheckBox();
                    String strVal="";
                    if (value!=null) strVal = value.toString();
                    if (strVal.equals("1"))
                    {
                        rendererComponent.setSelected(true);
                    } else
                    {
                        rendererComponent.setSelected(false);
                    }
                    return rendererComponent;
                }
            });
            DefaultCellEditor cellEditor = new DefaultCellEditor(new JCheckBox());
            cellEditor.setClickCountToStart(1);
            cellEditor.addCellEditorListener(new CellEditorListener()
            {
                public void editingCanceled(ChangeEvent e) {}
                public void editingStopped(ChangeEvent e)
                {
                    JCheckBox checkBox = (JCheckBox)((DefaultCellEditor)e.getSource()).getComponent();
                    System.out.println("isSelected = " + checkBox.isSelected());
                    if (checkBox.isSelected())
                    {
                        System.out.println("Sent 0");
                    } else
                    {
                        System.out.println("Sent 1");
                    }
                }
            });
            mgrdData.getColumnModel().getColumn(intCol).setCellEditor(cellEditor);
        }
    }

我用来查看小程序的 html 页面是:

<html>
  <body>
    <applet code="frmCheck.class" width="1016" height="822"></applet>
  </body>
</html>

要使其成为可执行文件(应用程序),您可以向其中添加以下 main() 函数(在 init() 函数上方,mtableModel 声明下方)

        public static void main(String[] args) {
        frmCheck myApplet = new frmCheck(); // define applet of interest
        Frame myFrame = new Frame("Applet Holder"); // create frame with title

        // Call applet's init method (since Java App does not
        // call it as a browser automatically does)
        myApplet.init();    

        // add applet to the frame
        myFrame.add(myApplet, BorderLayout.CENTER);
        myFrame.pack(); // set window to appropriate size (for its elements)
        myFrame.setVisible(true); // usual step to make frame visible

      } 

当您单击未选中的复选框时,控制台会显示:

isSelected = true
Sent 0

之后,当我再次单击该复选框(因此第二次)时,该复选框仍未选中,然后控制台显示:

isSelected = false
Sent 1

复选框在短时间内闪烁为选中状态,然后当我再次单击复选框时再次变为未选中状态(因此第三次),然后它的行为就像第一次被单击

我希望复选框: - 未选中并单击时发送 1 - 选中并单击时发送 0

真正的项目有点复杂:通过检查 JCheckBox,我向设备发送一条消息,该设备以其当前状态进行回答,该状态被处理并显示为选中的 JCheckBox。当我通过另一个通道更改设备中的状态时,处理工作正常,然后 JCheckBox 完美显示当前状态

我希望 JCheckBox 响应 1 单击:

  • 当它被选中并单击它时,它应该发送“REG SCH 4 = 0”
  • 当它未选中并单击它时,它应该发送“REG SCH 4 = 1”

好的,这是我到目前为止的代码:

JTable 创建如下:

JTable mgrdData;
DefaultTableModel mtableModel;
mtableModel = new DefaultTableModel(null,new String[0]);
mgrdData = new JTable(mtableModel);
mgrdData.getSelectionModel().addListSelectionListener(new RowListener());
mgrdData.setFillsViewportHeight(true);
String[] strHeader = {"Naam","Waarde"};
mtableModel.setColumnIdentifiers(strHeader);

列配置如下:

        addReadOnly(0);
//          addCombo(1,new String[]{"UIT","AAN"}); //this works fine
        addCheck(1);

第 0 列是只读的,第 1 列有 2 个可能的值,其中 addCombo(1,new String[]{"UIT","AAN"}); 完美的作品

函数 addReadOnly 和 addCombo 和 addCheck 如下:

private void addReadOnly(int intCol)
{
    JTextField txtField = new JTextField();
    txtField.setEditable(false);
    DefaultCellEditor cellEditor = new DefaultCellEditor(txtField);
    mgrdData.getColumnModel().getColumn(intCol).setCellEditor(cellEditor);
}

private void addCombo(int intCol,final String[] strItems)
{
    //add combobox
    mgrdData.getColumnModel().getColumn(intCol).setCellRenderer(new TableCellRenderer()
    {
        public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean isFocused,int row,int col)
        {
            JComboBox rendererComponent = new JComboBox(strItems);
            if (value!=null) rendererComponent.setSelectedItem(value.toString());
            return rendererComponent;
        }
    });
    DefaultCellEditor cellEditor = new DefaultCellEditor(new JComboBox(strItems));
    cellEditor.setClickCountToStart(1);
    cellEditor.addCellEditorListener(new CellEditorListener()
    {
        private boolean blnChanged=false;
        public void editingCanceled(ChangeEvent e) {}
        public void editingStopped(ChangeEvent e)
        {
            if (blnChanged==true)
            {
                JComboBox comboBox = (JComboBox)((DefaultCellEditor)e.getSource()).getComponent(); 
                sendVal(String.valueOf(comboBox.getSelectedIndex()));
                blnChanged = false;
            } else
            {
                blnChanged = true; 
            } 
        }
    });
    mgrdData.getColumnModel().getColumn(intCol).setCellEditor(cellEditor);
}

private void addCheck(int intCol)
{
    //add checkbox
    mgrdData.getColumnModel().getColumn(intCol).setCellRenderer(new TableCellRenderer()
    {
        public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean isFocused,int row,int col)
        {
            JCheckBox rendererComponent = new JCheckBox();
            String strVal="";
            if (value!=null) strVal = value.toString();
//              if (strVal.equals("AAN"))
            if (strVal.equals("1"))
            {
                rendererComponent.setSelected(true);
            } else
            {
                rendererComponent.setSelected(false);
            }
            return rendererComponent;
        }
    });
    DefaultCellEditor cellEditor = new DefaultCellEditor(new JCheckBox());
    cellEditor.setClickCountToStart(1);
    cellEditor.addCellEditorListener(new CellEditorListener()
    {
        public void editingCanceled(ChangeEvent e) {}
        public void editingStopped(ChangeEvent e)
        {
            JCheckBox checkBox = (JCheckBox)((DefaultCellEditor)e.getSource()).getComponent();
            System.out.println("isSelected = " + checkBox.isSelected());
            if (checkBox.isSelected())
            {
                sendVal("0");
                System.out.println("Sent 0");
            } else
            {
                sendVal("1");
                System.out.println("Sent 1");
            }
        }
    });
    mgrdData.getColumnModel().getColumn(intCol).setCellEditor(cellEditor);
}

点击 3 次后的测试结果:

选中 JCheckBox,单击 1 次后的结果:

isSelected = true
Sent : REG SCH 4 = 0
Sent 0

在此之后,未选中 JCheckBox

JCheckBox 未选中,单击 1 次后的结果:

isSelected = true
Sent : REG SCH 4 = 0
Sent 0

在此之后 JCheckBox 仍然未选中

JCheckBox 未选中但已单击一次,第二次单击后的结果:

isSelected = false
Sent : REG SCH 4 = 1
Sent 1

在此之后检查 JCheckBox

我搜索并找到了当您总是需要 2 次点击的解决方案,或者具有固定复选框而不是动态的解决方案,但不是像我这样的情况......

任何人都可以阐明一下吗?

4

2 回答 2

2

回答

问题是当复选框值是布尔值时,您将其视为字符串。

工作代码如下:

Boolean val = new Boolean(false);
if (value != null){
    val = (Boolean) value;
}
if (val.booleanValue()) {
    rendererComponent.setSelected(true);
}else{
     rendererComponent.setSelected(false);
}
return rendererComponent;

旧答案

我仍在查看它,但我认为问题可能是由于JCheckBox选择或不选择取决于:

if (strVal.equals("AAN"))
        {
            rendererComponent.setSelected(true);
        } else
        {
            rendererComponent.setSelected(false);
        }

不是"AAN"复选框的值而不是复选框的值吗?

此外,您每次都在创建一个新的 JCheckBox。

也许SSCCE可能有用。

于 2013-01-23T15:23:22.847 回答
1

您的代码的问题在于getTableCellRendererComponent方法。在这里,您总是使用JCheckBox. 所以每次它都需要一个新的JCheckBox并渲染列。

除此之外,无需将列呈现到Boolean. JTable它自己会呈现。您只需将列类型指定为Boolean.class.覆盖getColumnClass模型中的方法(DefaultTableModel,就像我展示的那样)并说 column-1 是布尔值。

小程序示例

import javax.swing.DefaultCellEditor;
import javax.swing.JApplet;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

    public class frmCheck extends JApplet
    {
        JTable mgrdData;
        DefaultTableModel mtableModel;

        public void init()
        {
            mtableModel = new DefaultTableModel() {
                @Override
                public Class<?> getColumnClass(int arg0) {
                    if(arg0 == 1) {
                        return Boolean.class; 
                    } else {
                        return super.getColumnClass(arg0);
                    }
                }
            };
            mtableModel.setColumnCount(2);
            mtableModel.setRowCount(4);
            mgrdData = new JTable(mtableModel);
//            mgrdData.getSelectionModel().addListSelectionListener(new RowListener());
            add(mgrdData);

            for (int i=1;i<mtableModel.getRowCount();i++)
            {
                addCheck(1);
            }
        }

        private class RowListener implements ListSelectionListener
        {
            public void valueChanged(ListSelectionEvent event)
            {
                if (event.getValueIsAdjusting()) return;
            }
        }

        private void addCheck(int intCol)
        {

            DefaultCellEditor cellEditor = new DefaultCellEditor(new JCheckBox());
             mgrdData.getColumnModel().getColumn(1).getCellEditor();
            cellEditor.setClickCountToStart(1);
            cellEditor.addCellEditorListener(new CellEditorListener()
            {
                public void editingCanceled(ChangeEvent e) {}
                public void editingStopped(ChangeEvent e)
                {
                    JCheckBox checkBox = (JCheckBox)((DefaultCellEditor)e.getSource()).getComponent();
                    System.out.println("isSelected = " + checkBox.isSelected());
                    if (checkBox.isSelected())
                    {
                        System.out.println("Sent 0");
                    } else
                    {
                        System.out.println("Sent 1");
                    }
                }
            });
            mgrdData.getColumnModel().getColumn(intCol).setCellEditor(cellEditor);
        }
    }

PS:我已经删除了未使用的代码。

于 2013-01-24T11:48:26.393 回答