JProgressBar не отображается правильно из ActionEvent - PullRequest
1 голос
/ 27 февраля 2011

В приведенном ниже коде 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();
    }
} 

Спасибо

Ответы [ 2 ]

2 голосов
/ 27 февраля 2011

Все, что вы делаете с компонентами 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 для фоновых задач.

1 голос
/ 27 февраля 2011

Проблема здесь в том, что вы выполняете dlg.show () для нового потока, который блокирует этот поток, и у вас есть Thread.sleep() в вашем основном потоке, так что почти все блокируется.Кроме того, JDialog.show() и hide() устарели, и вы, возможно, захотите использовать setVisible(true/false), но это не вызывает никаких проблем в вашем случае.Если вы пытаетесь в течение некоторого времени отобразить диалоговое окно с индикатором выполнения, а затем закрыть его, вот фиксированный код.Теперь есть второй поток, который позаботится о том, чтобы скрыть диалоговое окно через некоторое время, оставив основной поток, чтобы сделать свое дело.

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();
    }
} 
...