Java加载屏幕不显示任何GUI功能

时间:2015-03-10 23:14:47

标签: java swing swingworker

我正在尝试在Java中创建一个基本的加载屏幕,作为我的计算项目的一部分。问题是,如果我在没有加载时创建它的新实例,则显示GUI项目,但是,如果在我尝试显示GUI时有加载的东西,那么它将弹出GUI但没有文本或加载吧。

这是LoadingScreen类:

package gui;
import java.awt.*;
import javax.swing.*;
public class LoadingScreen extends Canvas
{
    private static final long serialVersionUID = 1L;
    JFrame frame = new JFrame();
    JPanel window = new JPanel();
    int width = 205;
    int height = 110;
    private JLabel progressText;
    private JProgressBar progressBar;
    private String loadingText;
    public boolean complete = false;
    public int progress = 0;
    Task task;
    public LoadingScreen(String loadingText)
    {
        this.loadingText = loadingText;
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        frame.setIconImage(new ImageIcon("res/logo/bt/128.png").getImage());
        frame.setSize(new Dimension(width, height));
        frame.add(window);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(false);
        window.setLayout(null);
        frame.getContentPane().add(window);
        frame.repaint();
    }
    public void setProgress(int percentage)
    {
        progress = percentage;
        frame.repaint();
    }
    public void setProgressText(String progressText)
    {
        this.progressText.setText(progressText);
        frame.repaint();
    }
    public void startLoadingScreen()
    {
        frame.setVisible(true);
        task = new Task();
        task.execute();
    }
    public void closeLoadingScreen()
    {
        setProgress(100);
        complete = true;
        frame.repaint();
        frame.setVisible(false);
    }
    class Task extends SwingWorker<Void, Void>
    {
        protected Void doInBackground() throws Exception
        {
            progressText = new JLabel(loadingText);
            Rectangle progressTextR = new Rectangle(10, 10, 180, 20);
            progressText.setBounds(progressTextR);
            progressText.setHorizontalAlignment(JLabel.CENTER);
            window.add(progressText);
            progressBar = new JProgressBar();
            Rectangle progressBarR = new Rectangle(10, 40, 180, 35);
            progressBar.setBounds(progressBarR);
            window.add(progressBar);
            frame.repaint();
            setProgress(0);
            while(!complete)
            {
                progressBar.setValue(progress);
            }
            return null;
        }
        public void done()
        {
            closeLoadingScreen();
        }
    }
}

我通常在另一个类的构造函数中将其称为

LoadingScreen loadingScreen = new LoadingScreen("Loading...");
loadingScreen.startLoadingScreen();
// Load some of the things I need to load.
loadingScreen.setProgress(50);
// Load the rest of the things I need to load.
loadingScreen.closeLoadingScreen();

如果它有帮助,这是加载的屏幕...

http://i.gyazo.com/3663c9e3ac720ce191d25fe558b2956f.png

有谁知道如何解决这个问题?如果是这样,我将不止感激! :)

谢谢!

1 个答案:

答案 0 :(得分:3)

你最大的问题是你的SwingWorker不尊重Swing线程,因为你在doInBackground方法中进行Swing调用,而你调用LoadingScreen的代码似乎在执行长期运行的代码 事件线程。这是倒退的,您需要交换它们。

这段代码:

// Load some of the things I need to load.
loadingScreen.setProgress(50);
// Load the rest of the things I need to load.

需要在doInBackground方法中。从doInBackground中设置SwingWorker的progress属性,并使用添加到SwingWorker的PropertyChangeListener来监听对此的更改。


例如,

import java.awt.BorderLayout;
import java.awt.Font;
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.Random;

import javax.swing.*;

public class MyLoadingTester extends JPanel {
   public MyLoadingTester() {
      add(new JButton(new LoadingAction()));
   }

   private class LoadingAction extends AbstractAction {
      public LoadingAction() {
         super("Load");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         final MyWorker myWorker = new MyWorker();
         Window win = SwingUtilities.getWindowAncestor(MyLoadingTester.this);
         final MyLoadingDialogPanel myLoadingDialogPanel = new MyLoadingDialogPanel("Loading a Bunch of Chit");
         final JDialog dialog = new JDialog(win, "Loading", ModalityType.APPLICATION_MODAL);
         dialog.add(myLoadingDialogPanel);
         dialog.pack();
         dialog.setLocationRelativeTo(win);

         myWorker.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
               if ("progress".equals(evt.getPropertyName())) {
                  int progress = ((Integer) evt.getNewValue()).intValue();
                  myLoadingDialogPanel.setProgress(progress);
               } else if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
                  dialog.dispose();
               }
            }
         });
         myWorker.execute();
         dialog.setVisible(true);
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("TestLoadingScreen");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new MyLoadingTester());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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

class MyLoadingDialogPanel extends JPanel {
   private JProgressBar progressBar = new JProgressBar(0, 100);

   public MyLoadingDialogPanel(String text) {
      progressBar.setStringPainted(true);

      setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
      setLayout(new BorderLayout());

      JLabel label = new JLabel(text, SwingConstants.CENTER);
      label.setFont(label.getFont().deriveFont(Font.BOLD, 18f));
      add(label, BorderLayout.PAGE_START);
      add(progressBar, BorderLayout.CENTER);
   }

   public void setProgress(int progress) {
      progressBar.setValue(progress);
   }
}

class MyWorker extends SwingWorker<Void, Void> {
   private static final int MAX = 100;
   private int myProgress = 0;
   private Random random = new Random();

   @Override
   protected Void doInBackground() throws Exception {
      // TODO put long-running code here
      // Load some of the things I need to load.
      // ..... call setProgress(...) as you're doing it
      // Load the rest of the things I need to load.

      // as an example
      while (myProgress < MAX) {
         myProgress += random.nextInt(5) + 5;
         Thread.sleep(200);
         setProgress(Math.min(MAX, myProgress));
      }
      return null;
   }
}