簡體   English   中英

JTable動態JCheckBox需要單擊1次取消選中,但需要單擊2次才能檢查

[英]JTable dynamic JCheckBox needs 1 click to uncheck, but 2 clicks to check

我對java很新,所以請原諒我犯的任何愚蠢的錯誤......

我有一個2列的JTable,其中第2列可以有4種類型:

  • 無法更改值的列
  • 一個可以包含任何文本字符串的列
  • 包含JComboBoxes的列
  • 包含JCheckBoxes的列

列類型是動態的,因為它們取決於接收的數據。

除JCheckBox外,所有類型都可以正常工作。 當我用帶有2個選項的JComboBox替換JCheckBox時,它工作正常。 所以我猜JCheckBox的代碼存在問題。

問題是 :

  • 當選中JCheckBox時,我只需要點擊一下就可以取消選中它
  • 但是當取消選中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);
        }
    }

我用來查看Applet的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,點擊一下后得到結果:

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

在此之后,JCheckBox未被選中

未選中JCheckBox,單擊一次后得到結果:

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

在此之后,JCheckBox仍然未經檢查

JCheckBox未經選中但已經點擊一次,第二次點擊后結果:

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

在此之后,檢查JCheckBox

我搜索並找到解決方案,當你總是需要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"不是Dropbox的值而不是checkbutton的值嗎?

還有,你每次都在創建一個新的JCheckBox。

也許SSCCE可能有用。

代碼的問題在於getTableCellRendererComponent方法。 在這里,您始終使用JCheckBox創建新組件。 所以每次它都采用新的JCheckBox並渲染列。

除此之外,不需要將列呈現為Boolean JTable它會自我渲染。 您只需將列類型指定為Boolean.class. 覆蓋模型中的getColumnClass方法(DefaultTableModel,就像我已經顯示的那樣),並說column-1是一個布爾值。

Applet Exampel

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:我刪除了未使用的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM