[英]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
而不是ButtonGroup
的JRadioButton
un_comment第343行,请参阅我的观点, JComboBox
为XxxCellEditor
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.