簡體   English   中英

為什么單擊“是/否”按鈕后JOptionPane的“確認對話框”不起作用?

[英]Why Confirm Dialog Box of JOptionPane is not taking action on clicking Yes/No button?

首先看到我的GUI:

在此處輸入圖片說明

背景:

我試圖通過GUI使用MongoDB集合的某些功能(CRUD)。

首先,用戶必須從第一個ComboBox中選擇一個現有的數據庫。 當用戶選擇一個選項時, private void jComboBoxDBNamePopupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt)函數將加載該數據庫下的所有集合。 在這里選擇博客

然后,用戶可以從第二個ComboBox的現有集合中選擇一個集合。 當用戶選擇一個集合時, private void jComboBoxCollectionNamePopupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt)函數將調用一個名為refreshTable()的函數來加載該集合下的所有Document。 在這里選擇帖子集合。

從第二個ComboBox中選擇選項時,如果所選擇的集合具有超過千個Document,它將要求用戶確認他是否確實要加載Document,因為這可能需要時間,或者可能是內存問題。 確認將通過JOptionPane.showConfirmDialog(...)

問題:

選擇收藏集帖子時 ,它會顯示對話框。 但是,單擊“ 是”或“ ”不會給出任何響應。 但為什么?

這些按鈕在圖片中帶有紅色下划線。

碼:

我的public boolean refreshTable()函數是:

public boolean refreshTable() {
    collections = db.getCollection((String) jComboBoxCollectionName.getSelectedItem());
    if(collections.count()>1000){
        int ret = JOptionPane.showConfirmDialog(this, "The table contains more than thousand row.\nThis may slow down the process and could cause Memory error.Are you sure to continue?","Too Large Collection ("+collections.count()+" Rows)",YES_NO_OPTION, INFORMATION_MESSAGE);
        if(ret!=YES_OPTION) return true;
    }
    //Some irrelevant codes
    return false;
}

研究:

我已經在Google上搜索了它,但無法解決問題。 以下是有關StackOverflow的一些問題,但我無法從中找出解決方案。

  1. JOptionPane確認對話框
  2. JOptionPane是/否選項確認對話框問題-Java
  3. JoptionPane ShowConfirmDialog

項目資料庫:

我的項目存儲庫在這里 如果需要,可以看看。

這可能是因為在其他JOptionPane上調用JOptionPane方法時,應在Swing的事件分配線程(EDT)上調用它。

您應該嘗試使用SwingUtilities實用程序方法來調用refreshTable,例如:

SwingUtilities.invokeLater(() -> refreshTable());

只是一個猜測,因為我們沒有從您提供的最小示例程序開始,但是,如果在長時間運行或占用大量CPU的代碼中調用此JOptionPane,並且該代碼在Swing事件線程上運行,它將凍結Swing事件線程,從而凍結您的GUI。 如果您不希望在后台線程中調用長時間運行的代碼或占用大量CPU的代碼,則可以這樣做,例如使用SwingWorker。

我查看了您的代碼,然后您在EDT上啟動GUI:

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            // this will be run on the EDT
            new UserInterface().setVisible(true);
        }
    });

因此,傑克的建議是不必要的,但是您正在EDT上進行所有數據庫調用,並且沒有遵循Swing線程規則,這會使您的圖表凍結,因此我的建議就是您需要遵循的建議。 首先,您需要學習Swing線程的基礎知識,因此,我建議您看一下本教程: 課程:Swing中的並發性

您可以通過兩個SwingWorkers和兩個JPropertyChangeListeners來解決:

  • 一個SwingWorker,稱為GetCollectionsWorker,它擴展了SwingWorker<Collections, Void> 我不知道第一個通用參數應該是什么,而應該是集合變量的類型。 該工作人員只需返回db.getCollection(selection); 從其doInBackground()方法。
  • 一個SwingWorker,稱為CreateTableModelWorker,它擴展了SwingWorker<DefaultTableModel, Void>並將集合傳遞到其構造函數中,並根據Collections持有的數據創建DefaultTableModel。
  • 一個名為ChangeCollectionListener的PropertyChangeListener,它偵聽CreateTableModelWorker何時完成,換句話說,它的newValue是SwingWorker.StateValue.DONE ,然后詢問用戶是否要繼續,如果這樣,則調用第二個SwingWorker。
  • 一個PropertyChangeListener,稱為CreateTableModelWorker,它偵聽CreateTableModelWorker完成的時間,並將表模型放入JTable中。

對於它的價值,我將在以下代碼中的這些地方實現。 同樣,對我來說,最大的未知數是collections變量代表什么類型,因此,第一個SwingWorker的泛型參數需要固定,並從Collections更改為您正在使用的參數:

// change to a void method
public void refreshTable() {
    String selection = (String) jComboBoxCollectionName.getSelectedItem();

    // SwingWorker to get collections
    GetCollectionsWorker getCollectionsWorker = new GetCollectionsWorker(selection);
    getCollectionsWorker.addPropertyChangeListener(new GetCollectionsListener());
    getCollectionsWorker.execute(); // run worker on background thread
}

// FIXME: Generic type Collections is wrong -- need to use correct type, whatever type collections is
private class GetCollectionsWorker extends SwingWorker<Collections, Void> {
    private String selection;

    public GetCollectionsWorker(String selection) {
        this.selection = selection;
    }

    @Override
    protected Collections doInBackground() throws Exception {
        // do database work here in a background thread
        return db.getCollection(selection);
    }
}

// class that listens for completion of the GetCollectionsWorker worker
class GetCollectionsListener implements PropertyChangeListener {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        // all this is done on the EDT
        if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
            // if worker is done, first get worker from listener
            GetCollectionsWorker worker = (GetCollectionsWorker) evt.getSource();
            try {
                // then extract the data that it's returning
                collections = worker.get();

                // then offer user option of continuing or not
                if (collections.count() > 1000) {
                    int ret = JOptionPane.showConfirmDialog(UserInterface.this,
                            "The table contains more than thousand row.\nThis may slow down the process and could cause Memory error.Are you sure to continue?",
                            "Too Large Collection (" + collections.count() + " Rows)", YES_NO_OPTION, INFORMATION_MESSAGE);
                    if (ret != YES_OPTION) {
                        return;
                    }
                }

                // our next worker, one to create table model
                CreateTableModelWorker createModelWorker = new CreateTableModelWorker(collections);
                // be notified when it is done
                createModelWorker.addPropertyChangeListener(new CreateModelListener());
                createModelWorker.execute(); // run on background thread

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

// worker to create table model on background thread
class CreateTableModelWorker extends SwingWorker<DefaultTableModel, Void> {
    private Collections collections;

    public CreateTableModelWorker(Collections collections) {
        this.collections = collections;
    }

    @Override
    protected DefaultTableModel doInBackground() throws Exception {
        documents = collections.find().into(new ArrayList<Document>());

        Set<String> colNames = new HashSet<>();

        for (Document doc : documents) {
            for (String key : doc.keySet()) {
                colNames.add(key);
            }
        }

        columns = colNames.toArray();
        Object[][] elements = new Object[documents.size()][columns.length];
        int docNo = 0;

        for (int i = 0; i < columns.length; i++) {
            if (((String) columns[i]).equalsIgnoreCase("_id")) {
                _idcol = i;
                break;
            }
        }

        for (Document doc : documents) {
            for (int i = 0; i < columns.length; i++) {
                if (doc.containsKey(columns[i])) {
                    elements[docNo][i] = doc.get(columns[i]);
                }
            }
            docNo++;
        }
        DefaultTableModel model = new DefaultTableModel(elements, columns);
        return model;
    }
}

private class CreateModelListener implements PropertyChangeListener {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        // all this is done on the EDT
        if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
            // if worker is done, first get worker from listener
            CreateTableModelWorker worker = (CreateTableModelWorker) evt.getSource();
            try {
                DefaultTableModel model = worker.get();
                jTableResultTable.setModel(model);
                UserInterface.this.model = model;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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