为什么我的框架什么都没显示?

时间:2014-12-12 02:40:44

标签: java swing awt

我想在关闭主框架时显示进度条窗口。但是,进度条窗口将不显示任何内容,我不知道它。这是代码。

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class MainFrame {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                MainFrame mainFrame = new MainFrame();
                mainFrame.createUI();
            }
        });
    }
    public void createUI(){
        JFrame frame = new JFrame();
        JPanel mainPanel = new JPanel(new BorderLayout());
        JButton button = new JButton("Close");
        button.setBorder(new EmptyBorder(20, 20, 20, 20));
        button.addActionListener(new ButtonListener());
        mainPanel.add(button,BorderLayout.CENTER);
        frame.add(mainPanel,BorderLayout.CENTER);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
    }

    class ButtonListener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            FeedbackBox feedbackBox = new FeedbackBox();
            feedbackBox.createUI();
            feedbackBox.increment(0, 100);
            try {
                feedbackBox.getThread().join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            feedbackBox.closeBox();
        }

    }
}

进度条窗口是:

import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class FeedbackBox {
    private JFrame frame;
    private JProgressBar progressBar;

    Thread thread;

    public void createUI(){
        frame = new JFrame("Reminder");
        MainPanel mainPanel = new MainPanel();
        frame.add(mainPanel,BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
    }

    public JProgressBar getProgressBar(){
        return progressBar;
    }

    public void closeBox(){
        frame.dispose();
    }

    public void increment(final int minimum,final int maximum){
        thread = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                for (int i = minimum; i <= maximum; i++) {
                    getProgressBar().setValue(i);
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });

        thread.start();
    }

    public Thread getThread(){
        return thread;
    }

    @SuppressWarnings("serial")
    class MainPanel extends JPanel{
        public MainPanel(){
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

            progressBar = new JProgressBar();
            progressBar.setStringPainted(true);
            progressBar.setIndeterminate(true);
            progressBar.setBackground(Color.white);
            progressBar.setForeground(Color.blue);
            JPanel topPanel = new JPanel();
            topPanel.add(progressBar);

            JLabel label = new JLabel("It is closing. ");
            label.setForeground(Color.blue);
            label.setBackground(Color.WHITE); 
            JPanel bottomPanel = new JPanel();
            bottomPanel.add(label);

            add(topPanel);
            add(Box.createVerticalStrut(10));
            add(bottomPanel);
        }
    }
}

如果我删除

try {
        feedbackBox.getThread().join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
}
feedbackBox.closeBox();

然后一切都会好的。为什么?感谢您的帮助。

基于@Hovercraft Full Of Eels的帮助。我修改了我的代码。但是,有线的东西仍在这里。除非我手动关闭进度条窗口,否则不会调用void propertyChange。

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class MainFrame {
    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                MainFrame mainFrame = new MainFrame();
                mainFrame.createUI();
            }
        });
    }
    public void createUI(){
        frame = new JFrame();
        JPanel mainPanel = new JPanel(new BorderLayout());
        JButton button = new JButton("Close");
        button.addActionListener(new ButtonListener());
        button.setBorder(new EmptyBorder(20, 20, 20, 20));
        mainPanel.add(button,BorderLayout.CENTER);
        frame.add(mainPanel,BorderLayout.CENTER);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
    }

    class ButtonListener implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            FeedbackBox feedbackBox = new FeedbackBox(frame,0,100,"It is closing");
            feedbackBox.displayDialog();
        }

    }
}


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;


public class FeedbackBox {
    private JDialog dialog;
    private MyWorker myWorker;
    private JProgressBar progressBar = new JProgressBar();

    public FeedbackBox(Window win,int minimum,int maximum,String title){
        myWorker = new MyWorker(minimum, maximum);
        MainPanel mainPanel = new MainPanel(minimum,maximum);
        myWorker.addPropertyChangeListener(new MyWorkerListener());
        dialog = new JDialog(win,title,ModalityType.APPLICATION_MODAL);
        dialog.add(mainPanel,BorderLayout.CENTER);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        dialog.setResizable(false);
        dialog.setLocationRelativeTo(win);
        dialog.pack();
    }

    public void displayDialog(){
        dialog.setVisible(true);
        myWorker.execute();
    }

    public void closeBox(){
        dialog.dispose();
    }

    @SuppressWarnings("serial")
    class MainPanel extends JPanel{
        public MainPanel(int minimum,int maximum){
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

            progressBar.setMinimum(minimum);
            progressBar.setMaximum(maximum);
            progressBar.setStringPainted(true);
            progressBar.setIndeterminate(true);
            progressBar.setBackground(Color.white);
            progressBar.setForeground(Color.blue);
            JPanel topPanel = new JPanel();
            topPanel.add(progressBar);

            JLabel label = new JLabel("It is closing.");
            label.setForeground(Color.blue);
            label.setBackground(Color.WHITE); 
            JPanel bottomPanel = new JPanel();
            bottomPanel.add(label);

            add(topPanel);
            add(Box.createVerticalStrut(10));
            add(bottomPanel);
        }
    }

    class MyWorkerListener implements PropertyChangeListener{

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            // TODO Auto-generated method stub
            if (evt.getPropertyName().equals(MyWorker.VALUE)) {
                System.out.println("myWorker.getValue()" + myWorker.getValue());
                progressBar.setValue(myWorker.getValue());
            }
            if (evt.getNewValue() == SwingWorker.StateValue.DONE && dialog != null) {
                closeBox();
            }
        }
    }
}

    class MyWorker extends SwingWorker<Void, Void>{
        public static final String VALUE = "value";
        private int value;
        private int minimum;
        private int maximum;

        public MyWorker(int minimum,int maximum){
            this.minimum = minimum;
            this.maximum = maximum;
            value = minimum;
        }

        @Override
        protected Void doInBackground() throws Exception {
            // TODO Auto-generated method stub
            for (int i = minimum; i <= maximum; i++) {
                setValue(i);
                Thread.sleep(30);
            }
            return null;
        }

        public void setValue(int i){
            int oldValue = this.value;
            int newValue = i;
            this.value = i;
            firePropertyChange(VALUE, oldValue, newValue);
        }

        public int getValue(){
            return value;
        }
    }

1 个答案:

答案 0 :(得分:4)

通过将您的线程与Swing事件线程连接,您可以使线程成为非后台线程,从而占用Swing事件线程,阻止它完成其工作 - 绘制GUI并与用户交互,这将冻结您的对话窗口(顺便说一句,它应该是JDialog而不是单独的JFrame)。解决方案:不加入线程。此外,您的后台线程不应该像当前那样更改Swing组件的状态。最好使用SwingWorker来让你在后台线程上保持事件线程和背景事物的Swing。

有关血腥的详细信息,请阅读Lesson: Concurrency in Swing - Oracle Documentation

例如:

import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;

import javax.swing.*;

@SuppressWarnings("serial")
public class ClosingDialogPanel {
   private JPanel mainPanel = new JPanel();
   private JProgressBar progressBar = new JProgressBar();
   private JDialog dialog;
   private MyWorker myWorker;

   public ClosingDialogPanel(Window win, int minimum, int maximum, String title) {
      myWorker = new MyWorker(minimum, maximum);
      progressBar.setMinimum(minimum);
      progressBar.setMaximum(maximum);
      myWorker.addPropertyChangeListener(new WorkerListener());
      progressBar.setStringPainted(true);
      mainPanel.add(progressBar);
      dialog = new JDialog(win, title, ModalityType.APPLICATION_MODAL);
      dialog.add(mainPanel);
      dialog.pack();
      dialog.setLocationRelativeTo(win);
   }

   public void displayDialog() {
      myWorker.execute();
      dialog.setVisible(true);
   }

   private class WorkerListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (MyWorker.VALUE.equals(evt.getPropertyName())) {
            progressBar.setValue(myWorker.getValue());
         }
         if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
            if (dialog != null && dialog.isVisible()) {
               dialog.dispose();
            }
            try {
               myWorker.get();
            } catch (InterruptedException e) {
               e.printStackTrace();
            } catch (ExecutionException e) {
               e.printStackTrace();
            }
         }
      }
   }

   private static void createAndShowGui() {
      final JFrame frame = new JFrame("Closing Frame");

      JButton closeBtn = new JButton(new AbstractAction("Close") {

         @Override
         public void actionPerformed(ActionEvent e) {
            final ClosingDialogPanel closingDlg = new ClosingDialogPanel(frame, 0,
                  200, "Closing");
            closingDlg.displayDialog();
         }
      });

      JPanel panel = new JPanel();
      panel.add(closeBtn);

      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(panel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }

}

class MyWorker extends SwingWorker<Void, Void> {
   public static final String VALUE = "value";
   private int value;
   private int minimum;
   private int maximum;

   public MyWorker(int minimum, int maximum) {
      this.minimum = minimum;
      this.maximum = maximum;
      value = minimum;
   }

   @Override
   protected Void doInBackground() throws Exception {
      for (int i = minimum; i <= maximum; i++) {
         setValue(i);
         Thread.sleep(30);
      }
      return null;
   }

   private void setValue(int i) {
      int oldValue = this.value;
      int newValue = i;
      this.value = i;
      firePropertyChange(VALUE, oldValue, newValue);
   }

   public int getValue() {
      return value;
   }
}