0

我对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 开始

单击 row1 上的 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());
  }
});
4

4 回答 4

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

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

于 2013-02-07T16:06:00.103 回答
1

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

public void actionPerformed(ActionEvent ae) {
  JRadioButton rb = (JRadioButton) ae.getSource();
  if (rb.isSelected()) {
    // do something depended on the button which was pressed
  }
}
于 2013-02-07T15:45:04.897 回答
1

尝试将 a 添加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无论如何,an 通常更适合单选按钮。

于 2013-02-07T15:47:35.853 回答
1
  • 覆盖所有通知程序并正确地作为JRadioButtonsin的工作并不容易ButtonGroupEditorComponent

    在此处输入图像描述

  • JComboBoxforXxxCellEditor代替JRadioButtons inButtonGroup

    在此处输入图像描述

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);
            }
        });
    }
}
于 2013-02-12T13:24:35.950 回答