[英]JComboBox setSelectedIndex causes Thread to Crash
我有一個問題,調用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的新手,特別是線程!
再次感謝
蒂姆
問題(幾乎可以肯定)與您在錯誤的線程上修改Swing組件的狀態有關。
一般規則是:
依賴於或修改Swing組件狀態的代碼應該在Event Dispatch Thread上執行 。
違反此規則有時可能難以檢測 - 特別是,只修改模型時,不一定要連接到GUI組件!
但是,在您的情況下,主要問題更明顯,因為(至少)有問題的調用
combo.setModel(new DefaultComboBoxModel(values.toArray(new String[values.size()])));
它發生在自己的線程上,並直接修改Swing組件。
正如評論中所建議的那樣,您應該明確考慮使用SwingWorker
。 有關SwingWorker
(以及Swing中的線程)的更多詳細信息可以在關於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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.