簡體   English   中英

JComboBox setSelectedIndex導致線程崩潰

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM