4

ユーザーがボタンをクリックすると、約10秒の長いタスクが実行されます。この間、進行状況バーをユーザーに表示したいと思います。ただし、ワーカースレッドはメインスレッドが使用する変数を設定するため、メインスレッドはワーカースレッドが終了するまで待機する必要があります。ワーカースレッドを待たないとNullPointerException、変数を使用するときにが表示されます。したがって、ワーカースレッドが終了したら、プログレスバーダイアログも閉じます。

join()プログレスバーダイアログを使用してワーカースレッドを待つと(興味深いことにプログレスバーはありませんが)、そこでハングします。

Thread runnable = new Thread() {

    public void run() {
        try {
            System.out.println("thread basladi");
            threadAddSlaveReturnMessage = request.addSlave(
                ipField.getText(), passField.getText(), 
                nicknameField.getText());
            System.out.println("thread bitti");

        } catch (LMCTagNotFoundException e) {
            e.printStackTrace();
        }

    }
};

Thread runnable_progress = new Thread() {

    public void run() {

        JTextArea msgLabel;
        JDialog dialog;
        JProgressBar progressBar;
        final int MAXIMUM = 100;
        JPanel panel;

        progressBar = new JProgressBar(0, MAXIMUM);
        progressBar.setIndeterminate(true);
        msgLabel = new JTextArea("deneme");
        msgLabel.setEditable(false);


        panel = new JPanel(new BorderLayout(5, 5));
        panel.add(msgLabel, BorderLayout.PAGE_START);
        panel.add(progressBar, BorderLayout.CENTER);
        panel.setBorder(BorderFactory.createEmptyBorder(11, 11, 11, 11));

        dialog = new JDialog(Frame.getFrames()[0], "baslik", true);
        dialog.getContentPane().add(panel);
        dialog.setResizable(false);
        dialog.pack();
        dialog.setSize(500, dialog.getHeight());
        dialog.setLocationRelativeTo(null);
        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dialog.setAlwaysOnTop(false);
        dialog.setVisible(true);
        msgLabel.setBackground(panel.getBackground());
    }
};

runnable.start();
System.out.println("runnable start");
runnable_progress.start();
System.out.println("progress start");
runnable.join();
System.out.println("runnable join");
runnable_progress.join();
System.out.println("progress join");


if (threadAddSlaveReturnMessage.equalsIgnoreCase("OK")) {
    fillInventoryTable(inventoryTable);
    JOptionPane.showMessageDialog(this, messages.getString("centrum.addslavepanel.SUCCESS"), null, JOptionPane.INFORMATION_MESSAGE);
}

「進行中の参加」

印刷されません。

4

3 に答える 3

4

ここでSwingWorkerを使用できます。短い例:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.godel.nio;

import java.awt.BorderLayout;
import java.util.List;
import javax.swing.*;

/**
 *
 * @author internet_2
 */
public class Test {

    public static void main(String[] args) {
        new Test().doJob();
    }

    public void doJob() {

        JTextArea msgLabel;
        JProgressBar progressBar;
        final int MAXIMUM = 100;
        JPanel panel;

        progressBar = new JProgressBar(0, MAXIMUM);
        progressBar.setIndeterminate(true);
        msgLabel = new JTextArea("deneme");
        msgLabel.setEditable(false);

        panel = new JPanel(new BorderLayout(5, 5));
        panel.add(msgLabel, BorderLayout.PAGE_START);
        panel.add(progressBar, BorderLayout.CENTER);
        panel.setBorder(BorderFactory.createEmptyBorder(11, 11, 11, 11));

        final JDialog dialog = new JDialog();
        dialog.getContentPane().add(panel);
        dialog.setResizable(false);
        dialog.pack();
        dialog.setSize(500, dialog.getHeight());
        dialog.setLocationRelativeTo(null);
        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dialog.setAlwaysOnTop(false);
        dialog.setVisible(true);
        msgLabel.setBackground(panel.getBackground());

        SwingWorker worker = new SwingWorker() {

            @Override
            protected void done() {
                // Close the dialog
                dialog.dispose();
            }

            @Override
            protected void process(List chunks) {
                // Here you can process the result of "doInBackGround()"
                // Set a variable in the dialog or etc.
            }

            @Override
            protected Object doInBackground() throws Exception {
                // Do the long running task here
                // Call "publish()" to pass the data to "process()"
                // return something meaningful
                return null;
            }
        };

        worker.execute();

    }
}

編集:「publish( )」を「doInBackground()」で呼び出して、データを「process()」に渡す必要があります。

于 2012-08-24T08:10:51.390 に答える
3
  1. Concurency is Swingに問題がある場合、すべてのスレッドが完了した後に GUI が表示されます

  2. JProgressBarで移動することは可能ですが (私はあなたのコードについて話しています)、あなたはしなければなりません

    • JDialogを作成して表示し、一度作成してこのコンテナを再利用します

    • 開始するThreadには、

    • からの方が良いかもしれませんRunnable#Thread

    • Swing GUI への出力は、次のようにラップする必要があります。invokeLater()

  3. これはまさにSwingWorkerPropertyChangeListenerを使用するための仕事です

于 2012-08-24T08:06:03.020 に答える
2

以前の回答が既に述べSwingWorkerたように、Swing で同時実行を使用したい場合は、行く方法です。
このSwingWorker と ProgressBar のチュートリアルは、すべてがどのように連携するかを理解するのに非常に役立ちます。

実際の問題に戻ります。ユーザーがボタンをクリックする必要があると述べたので、GUIを使用していると思います。問題は、あなたの「メインスレッド」が何をしているのかということです。本当に常に実行する必要がありますか?それのように見えません。スレッドには、ユーザーの操作の結果である別のスレッドによって設定される変数が必要であると言ったためです。要するに、とにかくユーザーの操作に依存しているのに、なぜ実行する必要があるのでしょうか?
通常の方法は、最初に必要なすべてのデータを取得してから、計算などを実行することです。あなたの場合、ボタンの ActionListener によって開始された単一のバックグラウンド スレッドですべてを実行するか (最初に変数を設定してから残りを実行)、変数を設定したスレッドが完了した後に他のスレッドを実行します。
たとえばdone()、 によって提供される メソッド を使用してSwingWorker、次のタスクを起動できます。または、本当に必要な場合は、 for ループでtruetask.isDone()が返されるのを待つことができます。ただし、チェックすることも忘れないでください。とにかく、デザインを再考する必要があると思います。提供された限られた情報からわかることは、私には複雑すぎるように見えるからです。isCancelled()

于 2012-08-24T09:05:21.433 に答える