簡體   English   中英

單擊單選按鈕具有舊的價值?

[英]Clicking on radiobutton gives old value?

我對Java很陌生,所以請不要太苛刻:)

我有一個JTable,在每個單元格中都有一個包含3個JRadioButtons的列。

JRadioButtons正確顯示,並且選擇了正確的JRadioButtons。

要將JRadioButtons放入JTable中,請使用setCellRenderer()和setCellEditor():

private void addRadio(int intCol)
{
  mgrdData.getColumnModel().getColumn(intCol).setCellRenderer(new RadioButtonRenderer());
  RadioButtonEditor butEdit = new RadioButtonEditor(new JCheckBox());
  butEdit.UseTcp(mtcpGrid);
  mgrdData.getColumnModel().getColumn(intCol).setCellEditor(butEdit);
}

下面是RadioButtonEditor類的代碼:

public class RadioButtonEditor extends DefaultCellEditor implements ItemListener
{
  public JPanel pnl = new JPanel();
  public ButtonGroup group1 = new ButtonGroup();
  public JRadioButton btnVA = new JRadioButton("VA");
  public JRadioButton btnUIT = new JRadioButton("UIT");
  public JRadioButton btnAAN = new JRadioButton("AAN");

  public tcp mtcpCon;

  public RadioButtonEditor(JCheckBox checkBox)
  {
    super(checkBox);
  }

  public void UseTcp(tcp tcpCon)
  {
    mtcpCon = tcpCon;
  }

  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
  {
    if (value==null) return null;
    group1.add(btnVA );
    group1.add(btnUIT );
    group1.add(btnAAN );
    pnl.add(btnVA );
    pnl.add(btnUIT );
    pnl.add(btnAAN );
    btnVA.setSelected(false);
    btnUIT .setSelected(false);
    btnAAN .setSelected(false);
    String strVal1 = (String)value;
    switch(Integer.parseInt(strVal1))
    {
      Case 0:
        btnVA.setSelected(true);
        break;
      Case 1:
        btnUIT.setSelected(true);
        break;
      Case 2:
        btnAAN.setSelected(true);
        break;
    }
    System.out.println("gettablecelleditorcomponent strVal1 : " + strVal1);
    return pnl;
  }

  public Object getCellEditorValue()
  {
    String strVal2="";
    if(btnVA.isSelected()  == true) strVal2="0";
    if(btnUIT.isSelected() == true) strVal2="1";
    if(btnAAN.isSelected() == true) strVal2="2";
    System.out.println("getcelleditorvalue strVal2 : " + strVal2);
    return strVal2;
  }

  public void itemStateChanged(ItemEvent e)
  {
    super.fireEditingStopped();
  }
}

下面是RadioButtonRenderer類的代碼:

public class RadioButtonRenderer implements TableCellRenderer
{
  public JPanel pnl = new JPanel();
  public ButtonGroup group1 = new ButtonGroup();
  public JRadioButton btnVA = new JRadioButton("VA");
  public JRadioButton btnUIT = new JRadioButton("UIT");
  public JRadioButton btnAAN = new JRadioButton("AAN");

  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
  {
    if (value==null) value="0";
    btnVA.putClientProperty("JComponent.sizeVariant","small");
    btnAAN.putClientProperty("JComponent.sizeVariant","small");
    btnUIT.putClientProperty("JComponent.sizeVariant","small");
    group1.add(btnVA );
    group1.add(btnUIT );
    group1.add(btnAAN );
    pnl.add(btnVA );
    pnl.add(btnUIT );
    pnl.add(btnAAN );
    btnVA.setSelected(false);
    btnUIT .setSelected(false);
    btnAAN .setSelected(false);
    switch(Integer.parseInt((String)value))
    {
      Case 0:
        btnVA.setSelected(true);
        break;
      Case 1:
        btnUIT.setSelected(true);
        break;
      Case 2:
        btnAAN.setSelected(true);
        break;
    }
    return pnl;
  }
}

我想檢測單擊了哪個JRadioButton,然后處理該新值。 我認為觸發事件應該在RadioButtonEditor類中,但是我不知道事件。

我在getTableCellEditor()和getCellEditorValue()事件中都添加了println(),但是都打印了舊值。

例如 :

從row0 = 0,row1 = 1,row2 = 2開始

在第1行上單擊2可得到:

gettablecelleditorcomponent : 1

現在row0 = 0,row1 = 2,row2 = 2在row0上單擊1給出:

getcelleditorvalue : 2
gettablecelleditorcomponent : 0

現在row0 = 1,row1 = 2,row2 = 2然后在row1上單擊0給出:

getcelleditorvalue : 1
gettablecelleditorcomponent : 2

現在row0 = 1,row1 = 0,row2 = 2然后在row2上單擊1給出:

getcelleditorvalue : 0
gettablecelleditorcomponent : 2

現在第0行= 1,第1行= 0,第2行= 1

由此可以看出:

getTableCellEditor() has the previous value of that row
getCellEditorValue() has the global previous value 

單擊JRadioButton的新值后,可以使用哪個事件?

[編輯]

我向表中添加了TableModelListener,但是getFirstRow()仍然顯示最后選擇的行,而不是用戶單擊單選按鈕的行。

因此,例如,當他們最后一次單擊第5行中的單選按鈕,現在單擊第7行中的單選按鈕時,則tabelChanged()中的getFirstRow()仍然顯示5

下面是我的TableModelListener的代碼:

mgrdData.getModel().addTableModelListener(new TableModelListener()
{
  public void tableChanged(TableModelEvent e)
  {
    System.out.println("column : " + e.getColumn());
    System.out.println("firstrow : " + e.getFirstRow());
  }
});

這是我的處理方式:

public class RadioButtonsCellEditor
    extends AbstractCellEditor
    implements TableCellEditor
{
    private final JRadioButton vuButton = new JRadioButton ("VA");
    private final JRadioButton uitButton = new JRadioButton ("UIT");
    private final JRadioButton aanButton = new JRadioButton ("AAN");
    private final ButtonGroup group = new ButtonGroup ();
    private final Box box = Box.createHorizontalBox ();

    public RadioButtonsCellEditor ()
    {
        super ();

        group.add (vuButton);
        group.add (uitButton);
        group.add (aanButton);

        box.add (vuButton);
        box.add (uitButton);
        box.add (aanButton);
    }

    @Override
    public Object getCellEditorValue ()
    {
        return
            vuButton.isSelected () ? "VU" :
            uitButton.isSelected () ? "UIT" :
            aanButton.isSelected () ? "AAN" : "";
    }

    @Override
    public Component getTableCellEditorComponent (JTable table, Object value,
            boolean isSelected, int row, int column)
    {
        vuButton.setSelected ("VA".equals (value));
        uitButton.setSelected ("UIT".equals (value));
        aanButton.setSelected ("AAN".equals (value));

        box.setBackground (table.getBackground ());
        box.setForeground (table.getForeground ());

        vuButton.setBackground (table.getBackground ());
        vuButton.setForeground (table.getForeground ());
        uitButton.setBackground (table.getBackground ());
        uitButton.setForeground (table.getForeground ());
        aanButton.setBackground (table.getBackground ());
        aanButton.setForeground (table.getForeground ());

        return box;
    }

    public static void main (String [] args)
    {
        JTable table = new JTable (
            new Object [][] {
                new Object [] {"1", "VU"},
                new Object [] {"2", "UIT"},
                new Object [] {"3", "AAN"}
            }, new Object [] {"#", "Value"});

        table.getColumnModel ().getColumn (1).setCellRenderer (new RadioButtonsCellRenderer ());
        table.getColumnModel ().getColumn (1).setCellEditor (new RadioButtonsCellEditor ());

        JFrame frame = new JFrame ("RadioButtonsCellRenderer");
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.getContentPane ().setLayout (new BorderLayout ());
        frame.getContentPane ().add (
            new JScrollPane (
                table,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
        frame.pack ();
        frame.setVisible (true);
    }

    private static class RadioButtonsCellRenderer
        extends Box
        implements TableCellRenderer
    {
        private final JRadioButton vuButton = new JRadioButton ("VA");
        private final JRadioButton uitButton = new JRadioButton ("UIT");
        private final JRadioButton aanButton = new JRadioButton ("AAN");
        private final ButtonGroup group = new ButtonGroup ();

        public RadioButtonsCellRenderer ()
        {
            super (BoxLayout.LINE_AXIS);

            group.add (vuButton);
            group.add (uitButton);
            group.add (aanButton);

            add (vuButton);
            add (uitButton);
            add (aanButton);
        }

        @Override
        public Component getTableCellRendererComponent (JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column)
        {
            vuButton.setSelected ("VU".equals (value));
            uitButton.setSelected ("UIT".equals (value));
            aanButton.setSelected ("AAN".equals (value));

            setBackground (table.getBackground ());
            setForeground (table.getForeground ());

            vuButton.setBackground (table.getBackground ());
            vuButton.setForeground (table.getForeground ());
            uitButton.setBackground (table.getBackground ());
            uitButton.setForeground (table.getForeground ());
            aanButton.setBackground (table.getBackground ());
            aanButton.setForeground (table.getForeground ());

            return this;
        }
    }
}

編輯器將僅提供新值,並將其設置為表模型。 您需要從表模型而不是從編輯器中讀取它。

如果我正確理解了您的問題,則只需在每個單選按鈕中添加相同的ActionListener

public void actionPerformed(ActionEvent ae) {
  JRadioButton rb = (JRadioButton) ae.getSource();
  if (rb.isSelected()) {
    // do something depended on the button which was pressed
  }
}

嘗試將TableModelListener添加到JTable中。

編輯只是更新JTable內部模型數據的過程。 存儲在編輯器中的值通常是臨時的且不可預測。

在編輯結束時,最終結果是表的基礎模型已更新。 然后將通知所有TableModelListeners。

更新

喔好吧。 現在的問題可能是,直到編輯器中的單選按鈕失去焦點之前,“編輯完成”事件才被觸發。 因此,單擊第7行實際上會觸發第5行剛剛失去焦點的事件。 單擊7只會使其具有焦點,並開始7的編輯過程。但是,您可以告訴編輯器何時完成編輯。 在編輯器中,嘗試如下操作:

public RadioButtonEditor(JCheckBox checkBox)
{
  super(checkBox);
  ActionListener editingListener = new ActionListener()
  {
    public void actionPerformed(ActionEvent e)
    {
      // editing is now complete - don't wait for focus to be lost
      // this will switch back to showing renderer
      //    and fire the event to tablemodellisteners
      stopCellEditing();
    }
  };
  btnVA.addActionListener(editingListener);
  btnUIT.addActionListener(editingListener);
  btnAAN.addActionListener(editingListener);
}

我認為您正在使用ItemListener沿着那條路線走,但是您尚未調用btnVA.addItemListener(this), etc. 但是,無論如何, ActionListener通常更適合單選按鈕。

  • 不容易的工作來覆蓋所有通知者,並正確地為ButtonGroup中的JRadioButtons作為EditorComponent

    在此處輸入圖片說明

  • JComboBox用於XxxCellEditor而不是ButtonGroupJRadioButton

    在此處輸入圖片說明

un_comment第343行,請參閱我的觀點, JComboBoxXxxCellEditor

import javax.swing.*;
import javax.swing.table.*;
import java.util.Date;
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.swing.UIManager.LookAndFeelInfo;

public class TableTestPanel extends JPanel {

    private static final String[] COLUMN_NAMES = {"List ID", "Expiration Date", "Status", "Date Created"};
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
    private static final long serialVersionUID = 1L;

    private static class StatusPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        private JRadioButton theSingleOption;
        private JRadioButton theMarriedOption;
        private JRadioButton theDivorcedOption;

        StatusPanel() {
            super(new GridLayout(3, 1));
            setOpaque(true);
            ButtonGroup buttonGroup = new ButtonGroup();
            theSingleOption = new JRadioButton("Single");
            theSingleOption.setOpaque(false);
            add(theSingleOption);
            buttonGroup.add(theSingleOption);
            theMarriedOption = new JRadioButton("Married");
            theMarriedOption.setOpaque(false);
            add(theMarriedOption);
            buttonGroup.add(theMarriedOption);
            theDivorcedOption = new JRadioButton("Divorced");
            theDivorcedOption.setOpaque(false);
            add(theDivorcedOption);
            buttonGroup.add(theDivorcedOption);
        }

        public Status getStatus() {
            if (theMarriedOption.isSelected()) {
                return Status.MARRIED;
            } else if (theDivorcedOption.isSelected()) {
                return Status.DIVORCED;
            } else {
                return Status.SINGLE;
            }
        }

        public void setStatus(Status status) {
            if (status == Status.MARRIED) {
                theMarriedOption.setSelected(true);
            } else if (status == Status.DIVORCED) {
                theDivorcedOption.setSelected(true);
            } else {
                theSingleOption.setSelected(true);
            }
        }
    }

    private static class Status {

        static final Status SINGLE = new Status("Single");
        static final Status MARRIED = new Status("Married");
        static final Status DIVORCED = new Status("Divorced");
        private final String myName; // for debug only

        private Status(String name) {
            myName = name;
        }

        @Override
        public String toString() {
            return myName;
        }
    }

    private static class TableEntry {

        private static int instanceNumber;
        private Long theId;
        private Date theExpirationDate;
        private Status theStatus;
        private Date theCreationDate;

        TableEntry() {
            instanceNumber++;
            theId = new Long(instanceNumber);
            theExpirationDate = new Date();
            theStatus = Status.SINGLE;
            theCreationDate = new Date();
        }

        TableEntry(Long anId, Date anExpirationDate, Status aStatus, Date aCreationDate) {
            theId = anId;
            theExpirationDate = anExpirationDate;
            theStatus = aStatus;
            theCreationDate = aCreationDate;
        }

        public Long getId() {
            return theId;
        }

        public Date getExpirationDate() {
            return theExpirationDate;
        }

        public Status getStatus() {
            return theStatus;
        }

        public Date getCreationDate() {
            return theCreationDate;
        }

        public void setId(Long anId) {
            theId = anId;
        }

        public void setExpirationDate(Date anExpirationDate) {
            theExpirationDate = anExpirationDate;
        }

        public void setStatus(Status aStatus) {
            theStatus = aStatus;
        }

        public void setCreationDate(Date aCreationDate) {
            theCreationDate = aCreationDate;
        }
    }

    private static class MyTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;
        private Vector<Object> theEntries;

        MyTableModel() {
            theEntries = new Vector<Object>();
        }

        @SuppressWarnings("unchecked")
        public void add(TableEntry anEntry) {
            int index = theEntries.size();
            theEntries.add(anEntry);
            fireTableRowsInserted(index, index);
        }

        public void remove(int aRowIndex) {
            if (aRowIndex < 0 || aRowIndex >= theEntries.size()) {
                return;
            }
            theEntries.removeElementAt(aRowIndex);
            fireTableRowsDeleted(aRowIndex, aRowIndex);

        }

        public int getRowCount() {
            return theEntries.size();
        }

        @Override
        public String getColumnName(int column) {
            return COLUMN_NAMES[column];
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return Long.class;
                case 1:
                    return Date.class;
                case 2:
                    return Status.class;
                case 3:
                    return Date.class;
            }
            return Object.class;
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            TableEntry entry = (TableEntry) theEntries.elementAt(rowIndex);
            switch (columnIndex) {
                case 0:
                    try {
                        entry.setId(new Long(Long.parseLong(aValue.toString())));
                    } catch (NumberFormatException nfe) {
                        return;
                    }
                    break;
                case 1:
                    entry.setExpirationDate((Date) aValue);
                    break;
                case 2:
                    entry.setStatus((Status) aValue);
                    break;
                case 3:
                    entry.setCreationDate((Date) aValue);
                    break;
                default:
                    return;
            }
            fireTableCellUpdated(rowIndex, columnIndex);
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

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

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            TableEntry entry = (TableEntry) theEntries.elementAt(rowIndex);
            switch (columnIndex) {
                case 0:
                    return entry.getId();
                case 1:
                    return entry.getExpirationDate();
                case 2:
                    return entry.getStatus();
                case 3:
                    return entry.getCreationDate();
            }
            return null;
        }
    }

    private static class DateRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (!(value instanceof Date)) {
                return this;
            }
            setText(DATE_FORMAT.format((Date) value));
            return this;
        }
    }

    private static class DateEditor extends AbstractCellEditor implements TableCellEditor {

        private static final long serialVersionUID = 1L;
        private JSpinner theSpinner;
        private Object value;

        DateEditor() {
            theSpinner = new JSpinner(new SpinnerDateModel());
            theSpinner.setOpaque(true);
            theSpinner.setEditor(new JSpinner.DateEditor(theSpinner, "dd/MM/yyyy"));
        }

        @Override
        public Object getCellEditorValue() {
            return theSpinner.getValue();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            theSpinner.setValue(value);
            if (isSelected) {
                theSpinner.setBackground(table.getSelectionBackground());
            } else {
                theSpinner.setBackground(table.getBackground());
            }
            return theSpinner;
        }
    }

    private static class StatusEditor extends AbstractCellEditor implements TableCellEditor {

        private static final long serialVersionUID = 1L;
        private StatusPanel theStatusPanel;

        StatusEditor() {
            theStatusPanel = new StatusPanel();
        }

        @Override
        public Object getCellEditorValue() {
            return theStatusPanel.getStatus();
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            theStatusPanel.setStatus((Status) value);
            if (isSelected) {
                theStatusPanel.setBackground(table.getSelectionBackground());
            } else {
                theStatusPanel.setBackground(table.getBackground());
            }
            return theStatusPanel;
        }
    }

    private static class StatusRenderer extends StatusPanel implements TableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            setStatus((Status) value);
            if (isSelected) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
            return this;
        }
    }
    private MyTableModel theTableModel;
    private JTable theTable;

    public TableTestPanel() {
        super(new BorderLayout(0, 5));
        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        theTableModel = new MyTableModel();
        theTable = new JTable(theTableModel);
        theTable.setDefaultEditor(Date.class, new DateEditor());
        theTable.setDefaultRenderer(Date.class, new DateRenderer());
        theTable.setDefaultEditor(Status.class, new StatusEditor());
        theTable.setDefaultRenderer(Status.class, new StatusRenderer());
// comment out the two preceding lines and uncomment the following one if you want a more standard editor
// theTable.setDefaultEditor(Status.class, new DefaultCellEditor(new JComboBox(new Status[]{Status.SINGLE, Status.MARRIED, Status.DIVORCED})));
        add(new JScrollPane(theTable), BorderLayout.CENTER);
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        toolBar.add(new AbstractAction("Add new") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                theTableModel.add(new TableEntry());
                packTable();
            }
        });
        toolBar.add(new AbstractAction("Remove") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                theTableModel.remove(theTable.getSelectedRow());
            }
        });
        add(toolBar, BorderLayout.NORTH);
    }

    private void packTable() {
        TableColumnModel columnModel = theTable.getColumnModel();
        int columnCount = theTable.getColumnCount();
        int rowCount = theTable.getRowCount();
        int[][] preferredHeights = new int[columnCount][rowCount];
        TableCellRenderer renderer;
        Component comp;
        for (int col = 0; col < columnCount; col++) {
            renderer = columnModel.getColumn(col).getCellRenderer();
            if (renderer == null) {
                renderer = theTable.getDefaultRenderer(theTableModel.getColumnClass(col));
            }
            for (int row = 0; row < rowCount; row++) {
                comp = renderer.getTableCellRendererComponent(theTable, theTableModel.getValueAt(row, col), false, false, row, col);
                preferredHeights[col][row] = (int) comp.getPreferredSize().getHeight();
            }
        }
        for (int row = 0; row < rowCount; row++) {
            int pref = 0;
            for (int col = 0; col < columnCount; col++) {
                pref = Math.max(pref, preferredHeights[col][row]);
            }
            theTable.setRowHeight(row, pref);
        }
    }

    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();
        }
        final JFrame frame = new JFrame("TestRadioButtonRenderer");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new TableTestPanel());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                frame.setSize(400, 300);
                frame.setVisible(true);
            }
        });
    }
}

暫無
暫無

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

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