单击单选按钮会显示旧值?

时间:2013-02-07 15:30:04

标签: java swing jtable tablecelleditor jradiobutton

我对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类中,但我不知道事件。

我将println()添加到getTableCellEditor()以及getCellEditorValue()事件中,但都打印旧值。

例如:

从row0 = 0开始,row1 = 1,row2 = 2

点击第1行上的2给出:

gettablecelleditorcomponent : 1

现在row0 = 0,row1 = 2,row2 = 2 点击第0行上的1给出:

getcelleditorvalue : 2
gettablecelleditorcomponent : 0

现在row0 = 1,row1 = 2,row2 = 2 然后单击row1上的0给出:

getcelleditorvalue : 1
gettablecelleditorcomponent : 2

现在row0 = 1,row1 = 0,row2 = 2 然后点击第2行上的1给出:

getcelleditorvalue : 0
gettablecelleditorcomponent : 2

现在row0 = 1,row1 = 0,row2 = 1

从中可以看出:

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

点击后,我可以使用哪个事件来获取JRadioButton的新值?

[编辑]

我在表中添加了一个TableModelListener,但是getFirstRow()仍然显示最后选择的行,而不是用户点击radiobutton的行。

例如,当他们最后一次点击第5行的单选按钮时,现在点击第7行的radiobuttion,然后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());
  }
});

4 个答案:

答案 0 :(得分:2)

我将如何做到这一点:

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

编辑器将提供将设置到表模型中的新值。您需要从表模型中读取它,而不是从编辑器中读取它。

答案 1 :(得分:1)

如果我正确理解您的问题,您只需在每个单选按钮上添加相同的ActionListener

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

答案 2 :(得分:1)

尝试向您的JTable添加TableModelListener

编辑只是更新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通常对于无线电按钮更好。

答案 3 :(得分:1)

  • 不能轻易覆盖所有通知,并且JRadioButtons ButtonGroup EditorComponent正确覆盖所有通知,JComboBox

    enter image description here

  • XxxCellEditor

    中使用JRadioButton代替ButtonGroup代替JComboBox

    enter image description here

un_comment第343行。,请参阅我的观点,XxxCellEditorimport 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); } }); } }

{{1}}