[英]How to fix java.awt.IllegalComponentStateException for JTable with JComboBox cell editor?
I need to show dynamic data set for each row of a table, so I use DefaultCellEditor(JComboBox) and load data to his DefaultComboBoxModel using PopupMenuListener. 我需要为表的每一行显示动态数据集,因此我使用DefaultCellEditor(JComboBox)并使用PopupMenuListener将数据加载到他的DefaultComboBoxModel。 My problem is: when I click a cell of table, JComboBox doesn't show popup list and app throws exception. 我的问题是:当我单击表格的单元格时,JComboBox不显示弹出列表,应用程序抛出异常。 I use Java 7. 我使用Java 7。
How to fix it? 怎么解决?
Code sample: 代码示例:
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TestTable extends JFrame implements PopupMenuListener
{
public TestTable()
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
String[] data = new String[]{"A", "B"};
DefaultTableModel mdlTable = new DefaultTableModel();
mdlTable.addColumn("Col");
for (int i = 0; i < 3; i++) {
mdlTable.addRow(data);
}
JTable tbl = new JTable(mdlTable);
TableColumnModel mdlColumn = tbl.getColumnModel();
TableColumn clm = mdlColumn.getColumn(0);
DefaultComboBoxModel mdlComboBox = new DefaultComboBoxModel();
JComboBox cmb = new JComboBox(mdlComboBox);
cmb.addPopupMenuListener(this);
clm.setCellEditor(new DefaultCellEditor(cmb));
setContentPane(new JScrollPane(tbl));
setSize(200, 200);
setVisible(true);
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
JComboBox cmb = (JComboBox) e.getSource();
DefaultComboBoxModel mdl = (DefaultComboBoxModel) cmb.getModel();
mdl.removeAllElements();
String[] data = new String[]{"A", "B", "C", "D"};
for (String item : data) {
mdl.addElement(item);
}
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
{
}
@Override
public void popupMenuCanceled(PopupMenuEvent e)
{
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new TestTable();
}
});
}
}
Full stack trace: 完整堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location
at java.awt.Component.getLocationOnScreen_NoTreeLock(Component.java:2048)
at java.awt.Component.getLocationOnScreen(Component.java:2022)
at javax.swing.JPopupMenu.show(JPopupMenu.java:942)
at javax.swing.plaf.basic.BasicComboPopup.show(BasicComboPopup.java:208)
at javax.swing.plaf.basic.BasicComboPopup.togglePopup(BasicComboPopup.java:1128)
at javax.swing.plaf.basic.BasicComboPopup$Handler.mousePressed(BasicComboPopup.java:825)
at java.awt.Component.processMouseEvent(Component.java:6513)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6281)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4698)
at javax.swing.plaf.basic.BasicTableUI$Handler.repostEvent(BasicTableUI.java:948)
at javax.swing.plaf.basic.BasicTableUI$Handler.adjustSelection(BasicTableUI.java:1110)
at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(BasicTableUI.java:1038)
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:280)
at java.awt.Component.processMouseEvent(Component.java:6513)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6281)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4489)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:740)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:699)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:713)
at java.awt.EventQueue$4.run(EventQueue.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:710)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
A simple workaround is changing the model, instead of adding elements to the existing one: 一个简单的解决方法是更改模型,而不是向现有模型添加元素:
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e)
{
JComboBox<String> cmb = (JComboBox<String>) e.getSource();
cmb.setModel(new DefaultComboBoxModel<>(new String[]{"A", "B", "C", "D"}));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.