1

以下のコードでは、が内部から呼び出されJProgressBarた場合は正しく表示されますが、 の結果として呼び出された場合は正しく表示されません。インターフェイスがフリーズしているようです。何が問題ですか?doSomething()main()ActionEvent

import java.awt.BorderLayout; 

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Vector;


public class ThreadedDialog  extends JFrame implements ActionListener{                
    private JDialog dlg;
    private JButton button;

    private void buildInterface(){
        button = new JButton("do stuff;");
        button.addActionListener(this);
        this.getContentPane().setLayout(new BorderLayout()); 
        this.getContentPane().add(BorderLayout.CENTER, button); 


        dlg = new JDialog(this, "Progress Dialog", true); 
        JProgressBar dpb = new JProgressBar(0, 500); 
        dlg.getContentPane().setLayout(new BorderLayout()); 
        dlg.getContentPane().add(BorderLayout.CENTER, dpb); 
        dlg.getContentPane().add(BorderLayout.NORTH, new JLabel("Progress..."));         
        dlg.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); 
        dlg.setSize(300, 75); 
        dlg.setLocationRelativeTo(this);
        dpb.setIndeterminate(true);        
    }

    public void doSomething(){
        Thread t = new Thread(new Runnable(){ 
            public void run() { 
                dlg.show(); 
            } 
        });                          
        t.start();     
        try { 
            for (int i=0; i<100; i++){
                System.out.println("wtf is going on here?");
                Thread.sleep(5000);
            }
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        }
        dlg.hide();         
    }

    public static void main(String[] args) { 
        ThreadedDialog me = new ThreadedDialog();

        me.buildInterface();        
        me.pack();
        me.setVisible(true);
        me.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        //me.doSomething();
    }

    public void actionPerformed(ActionEvent event) {
        doSomething();
    }
} 

ありがとう

4

2 に答える 2

2

Swing コンポーネントで行うことはすべて、イベント ディスパッチ スレッド (EDT) (つまり、Swing がイベントを呼び出すために使用するスレッド) で行う必要があります。時間のかかるバックグラウンド操作を実行するには、スレッドを起動する必要があります。

コードでは、逆のことを行います。別のスレッドでダイアログを表示しようとし、EDT で長い操作を実行します。

固定コードは次のとおりです。

package fr.free.jnizet.stackoverflow;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;


public class ThreadedDialog  extends JFrame implements ActionListener{
    private JDialog dlg;
    private JButton button;

    private void buildInterface(){
        button = new JButton("do stuff;");
        button.addActionListener(this);
        this.getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(BorderLayout.CENTER, button);


        dlg = new JDialog(this, "Progress Dialog", true);
        JProgressBar dpb = new JProgressBar(0, 500);
        dlg.getContentPane().setLayout(new BorderLayout());
        dlg.getContentPane().add(BorderLayout.CENTER, dpb);
        dlg.getContentPane().add(BorderLayout.NORTH, new JLabel("Progress..."));
        dlg.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dlg.setSize(300, 75);
        dlg.setLocationRelativeTo(this);
        dpb.setIndeterminate(true);
    }

    public void doSomething(){
        // create a thread for the background task
        Thread t = new Thread(new Runnable(){
            public void run() {
                try {
                    for (int i=0; i<100; i++){
                        System.out.println("wtf is going on here?");
                        Thread.sleep(5000);
                    }
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // when the background task is finished, hide the dialog in the EDT.
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        dlg.setVisible(false);
                    }

                });
            }
        });
        t.start();

        // show the dialog in the EDT
        dlg.setVisible(true);
    }

    public static void main(String[] args) {
        // create the GUI in the EDT
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                ThreadedDialog me = new ThreadedDialog();

                me.buildInterface();
                me.pack();
                me.setVisible(true);
                me.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });

    }

    public void actionPerformed(ActionEvent event) {
        doSomething();
    }
}

このチュートリアルを読んで、バックグラウンド タスクに SwingWorker を使用する方法を学習してください。

于 2011-02-27T16:25:09.397 に答える
1

ここでの問題は、そのスレッドをブロックする新しいスレッドで dlg.show() を実行していThread.sleep()て、メインスレッドにあるため、ほとんどすべてがブロックされていることです。またJDialog.show()、 とhide()は非推奨であり、 を使用したいかもしれませんsetVisible(true/false)が、それはあなたのケースでは問題を引き起こしていませんでした. 進行状況バーを含むダイアログをしばらく表示してから閉じようとしている場合は、修正されたコードを次に示します。しばらくメインスレッドを離れてダイアログを非表示にする処理を行う 2 番目のスレッドがあります。

import java.awt.BorderLayout;

import javax.swing.*;
import java.awt.event.*;

public class ThreadedDialog extends JFrame implements ActionListener {
    private JDialog dlg;
    private JButton button;

    private void buildInterface() {
        button = new JButton("do stuff;");
        button.addActionListener(this);
        this.getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(BorderLayout.CENTER, button);

        dlg = new JDialog(this, "Progress Dialog", true);
        JProgressBar dpb = new JProgressBar(0, 500);
        dlg.getContentPane().setLayout(new BorderLayout());
        dlg.getContentPane().add(BorderLayout.CENTER, dpb);
        dlg.getContentPane().add(BorderLayout.NORTH, new JLabel("Progress..."));
        dlg.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dlg.setSize(300, 75);
        dlg.setLocationRelativeTo(this);
        dpb.setIndeterminate(true);

    }

    public void doSomething() {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                dlg.setVisible(true);

            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    System.out.println("wtf is going on here?");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                dlg.setVisible(false);

            }
        });
        t1.start();
        t2.start();

    }

    public static void main(String[] args) {
        ThreadedDialog me = new ThreadedDialog();

        me.buildInterface();
        me.pack();
        me.setVisible(true);
        me.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // me.doSomething();
    }

    public void actionPerformed(ActionEvent event) {
        doSomething();
    }
} 
于 2011-02-27T16:13:55.887 に答える