我遇到调用JComboBox.setSelectedIndex(0)导致的问题 我的程序崩溃了。任何帮助将不胜感激!!
在itemStateChanged()上启动一个新的Thread来处理UpdateAllForms。
UpdateAllForms调用updateComboModel(),它查询SQL数据库以更新ComboBoxModel并添加一个附加选项'Select ...'
这一切都正常,但是如果我添加JComboBox.setSelectedIndex(0) 程序崩溃,没有异常等我假设问题是线程?
itemStateChanged()方法:
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.DESELECTED) {
Runnable updateRunnable = new UpdateAllForms(e.getSource());
new Thread(updateRunnable).start();
}
}
UpdateAllForms类:
// <<=== UpdateAllForms Class ===>>
// Only Updates Forms below the Current Form
// Must be ran as a Separate Thread due to swing concurrency
// ==============================================================================
public class UpdateAllForms implements Runnable {
Object source = null;
public UpdateAllForms(Object source) {
this.source = source;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean shouldUpdate = false;
Logger.write("PropConfDialog.updateAllForms");
// Loop through Forms
for (int formCount = 0; formCount < dataInputForms.get(1).size(); formCount++) {
Component curForm = dataInputForms.get(1).get(formCount);
// Update Forms after current form
if (shouldUpdate) {
if (curForm instanceof JSQLComboPanel) {
JSQLComboPanel panel = (JSQLComboPanel) curForm;
// Resets the where String
panel.setWhereString(getInputString(panel.getInputID()));
panel.updateComboModel();
shouldUpdate = true;
continue;
} else if (curForm instanceof JSQLLabelPanel) {
JSQLLabelPanel panel = (JSQLLabelPanel) curForm;
panel.setWhereString(getInputString(panel.getInputID()));
panel.updateLabel();
shouldUpdate = true;
Logger.write("LABEL CAN CARRY OUT");
continue;
}// End if/else
} // End should update
if (source == ((JSQLComboPanel) dataInputForms.get(1).get(formCount)).getComboBox()) {
shouldUpdate = true;
}// End if
}// End Loop
}// End updateAllCombos()
}// End UpdateAllForms Class
JSQLComboPanel类 - updateComboModel方法!!这就是问题!!!如果我打电话 combo.setSelectedIndex(0)在此方法中程序崩溃。
public void updateComboModel(){
if(comboType == TYPE_DRIVEN_COMBO){
ArrayList values = SQLTools.getColValues(lkTable, lkNameCol);
combo.setModel(new DefaultComboBoxModel(values.toArray(new String[values.size()])));
}else if(comboType == TYPE_WHERE_COMBO){
ArrayList values = SQLTools.executeJoin(fkTable, fkIDCol, fkNameCol, lkTable, lkIDCol, lkNameCol, whereString);
combo.setModel(new DefaultComboBoxModel(values.toArray(new String[values.size()])));
}else if(comboType == TYPE_WHERE_LINKED_COMBO){
ArrayList values = SQLTools.executeLinkTableJoin(fkTable, fkIDCol, fkNameCol, linkTable, fkIDCol, lkIDCol, lkTable, lkIDCol, lkNameCol,whereString);
combo.setModel(new DefaultComboBoxModel(values.toArray(new String[values.size()])));
}//End if/else
combo.insertItemAt("Select...", 0);
//combo.setSelectedIndex(0);
combo.repaint();
}//End updateComboModel()
如果有人可以放弃任何光线,那就太棒了!我是Java的新手,特别是线程!
再次感谢
添
答案 0 :(得分:0)
问题(几乎可以肯定)与您在错误的线程上修改Swing组件的状态有关。
一般规则是:
依赖于或修改Swing组件状态的代码应该在Event Dispatch Thread上执行。
违反此规则有时可能难以检测 - 特别是当仅修改模型时,它不一定与GUI组件有连接!
然而,在你的情况下,主要问题更明显,因为(至少)有问题的电话
combo.setModel(new DefaultComboBoxModel(values.toArray(new String[values.size()])));
发生在自己的线程上,并直接修改Swing组件。
正如评论中所建议的那样,您应该明确考虑使用SwingWorker
。有关SwingWorker
(以及一般Swing中的线程)的更多详细信息,请参阅有关Concurrency In Swing的文章
您的问题的快速解决方法可能如下:
...
// Remove this line
//combo.setModel(new DefaultComboBoxModel(values.toArray(new String[values.size()])));
// Replace it with this line
setModelOnEDT(combo, new DefaultComboBoxModel(values.toArray(new String[values.size()]));
并创建一个这样的方法:
private static void setModelOnEDT(
final JComboBox comboBox, final ComboBoxModel model)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
comboBox.setModel(model);
}
});
}
这肯定不是最漂亮的解决方案,但最简单,直到您修改代码以使用SwingWorker
。