第一次调用JFrame后,JFrame显示为空白

时间:2016-10-12 15:26:50

标签: java swing jframe jpanel

这个JFrame是我第一次在应用程序运行时调用它,效果很好。但是当我尝试打开一个新文件时,进度条意味着返回到屏幕。查看屏幕抓取以了解它应如何看待其后的外观。

public ArrayList<Data> handleData(File fileToOpen) throws FileNotFoundException {
        ArrayList<Data> handle = new ArrayList<Data>();
    //clear the arraylist the second time round
    handle.clear();

    BufferedReader reader = new BufferedReader(new FileReader(fileToOpen));
    //buffer used for scanner
    int lines = 0;
    //find out the value of lines here

    JFrame loader = new JFrame();
    JPanel loadPanel = new JPanel();
    JProgressBar progressBar = new JProgressBar(0, lines);
    JLabel label = new JLabel();

    loader.setDefaultCloseOperation(EXIT_ON_CLOSE);
    label.setText("Loading Data...");
    loadPanel.add(label);
    loadPanel.add(progressBar);
    loader.add(loadPanel);
    loader.pack();
    loader.setVisible(true);

    //Do a load of stuff which increments the progress bar
    loader.setVisible(false);

    return handle;
}

这是进度条和JFrame的外观:

This is how the progress bar and JFrame should look.

这是第二次进度条的显示方式:

This Is how the progress bar looks the second time

所有代码:

package Default;

import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class ReadIn extends JFrame {

public File openFile() {

    File fileToOpen = null;

    JFileChooser fileChooser = new JFileChooser();
    int modalToComponent = fileChooser.showOpenDialog(this);
    if (modalToComponent == JFileChooser.APPROVE_OPTION) {
        fileToOpen = fileChooser.getSelectedFile();
    } else if (modalToComponent == JFileChooser.CANCEL_OPTION) {
        System.exit(1);
    }

    return fileToOpen;

}

public ArrayList<Data> handleData(File fileToOpen) throws FileNotFoundException {
    ArrayList<Data> handle = new ArrayList<Data>();
    handle.clear();

    BufferedReader reader = new BufferedReader(new FileReader(fileToOpen));

    int lines = 0;

    try {
        while (reader.readLine() != null)
            lines++;
        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    Scanner sc = new Scanner(fileToOpen);

    System.out.println(sc.nextLine());
    System.out.println(sc.nextLine());
    System.out.println("Reading Data...");

    sc.nextLine();

    String split = sc.nextLine();
    Scanner splitter = new Scanner(split);

    JDialog loader = new JDialog();
    JPanel loadPanel = new JPanel();
    JProgressBar progressBar = new JProgressBar(0, lines);
    JLabel label = new JLabel();

    loader.setDefaultCloseOperation(HIDE_ON_CLOSE);
    label.setText("Loading Data...");
    loadPanel.add(label);
    loadPanel.add(progressBar);
    loader.add(loadPanel);
    loader.pack();
    loader.setVisible(true);

    while (splitter.hasNext()) {

        String peek = splitter.next();
        if (peek.equals("Timestamp")) {
            peek = peek + splitter.next();
        }
        Data temp = new Data();
        temp.setHeading(peek);
        handle.add(temp);

    }

    while (sc.hasNextDouble()) {
        progressBar.setValue(progressBar.getValue() + 1);
        for (int i = 0; i < handle.size(); i++) {
            handle.get(i).getValues().add(sc.nextDouble());

        }

    }
    System.out.println("Data Loaded");
    splitter.close();
    sc.close();
    loader.setVisible(false);
    System.out.println("On EDT?: " + SwingUtilities.isEventDispatchThread());
    return handle;
}

}

1 个答案:

答案 0 :(得分:2)

如果您没有发布有效的minimal example program,我们就无法绝对保证您的问题的原因,图像表明这是一个Swing线程问题,您可能已经运行了很长时间的代码,可能这里:

//Do a load of stuff which increments the progress bar

阻止了Swing事件线程,这导致Swing GUI不自行绘制。

如果是这样,解决方案是改进您的代码,使其尊重Swing事件线程,以便长时间运行的代码在后台线程中运行,例如通过SwingWorker。

其他问题:您显示的窗口看起来是“依赖”窗口而不是主应用程序窗口。如果是这样,它不应该被创建为JFrame而是作为JDialog创建,无论是模态还是非模态,取决于您的需要。

另外 - 为什么它第一次有效?可能是第一次,上面的代码不在Swing事件线程EDT上运行,而第二次调用该代码时,它实际上是在EDT上运行的。您可以通过调用SwingUtilities.isEventDispatchThread()并打印出结果来对此进行测试。如,

System.out.println("On EDT?: " + SwingUtilities.isEventDispatchThread());

例如:

import java.awt.BorderLayout;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import javax.swing.*;

public class UpdateDataEg extends JPanel {
    protected static final int MAX_LINES = 200;

    public UpdateDataEg() {
        setPreferredSize(new Dimension(500, 400));
        add(new JButton(new UpdateDataAction("Update Data", KeyEvent.VK_U)));
    }

    // this must be a void method as you'll get the result from a callback, not
    // from this method
    public void handleData(final File fileToOpen) {
        int lines = 0;
        // find out the value of lines here

        Window window = SwingUtilities.getWindowAncestor(UpdateDataEg.this);
        JDialog loader = new JDialog(window, "Progress", ModalityType.APPLICATION_MODAL);
        JPanel loadPanel = new JPanel(new BorderLayout());
        final JProgressBar progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true);
        JLabel label = new JLabel();

        label.setText("Loading Data...");
        loadPanel.add(label, BorderLayout.PAGE_START);
        loadPanel.add(progressBar);
        loader.add(loadPanel);
        loader.pack();
        loader.setLocationRelativeTo(window);

        final SwingWorker<ArrayList<Data>, Void> myWorker = new SwingWorker<ArrayList<Data>, Void>() {

            @Override
            protected ArrayList<Data> doInBackground() throws Exception {
                ArrayList<Data> handle = new ArrayList<Data>();
                // clear the arraylist the second time round
                handle.clear();

                int lines = 0;
                // !! BufferedReader reader = new BufferedReader(new FileReader(fileToOpen));

                // !! long code here to do calculations and place into ArrayList<Data>
                // emulated by Thread.sleep
                // !! set progress property here so that listener can update
                while (lines < MAX_LINES) {
                    lines += (int) (10 * Math.random());
                    int myProgress = (int) ((lines * 100) / MAX_LINES);
                    myProgress = Math.min(100, myProgress);
                    setProgress(myProgress);
                    Thread.sleep(200);
                }

                return handle;
            }

        };

        // our callback
        myWorker.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent pcEvt) {
                if (pcEvt.getPropertyName().equals("progress")) {
                    int progress = myWorker.getProgress();
                    progressBar.setValue(progress);
                } else if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
                    // if the worker has finished
                    loader.setVisible(false);

                    try {
                        ArrayList<Data> data = myWorker.get();
                        // use data here
                    } catch (InterruptedException | ExecutionException e) {
                        // TODO handle the exceptions
                        e.printStackTrace();
                    }
                }
            }
        });

        myWorker.execute();
        // if the dialog is modal, this must be last
        loader.setVisible(true);

        // delete this call as this would be done from the callback
        // loader.setVisible(false);

        // delete this as this is obtained in the callback
        // return handle;
    }

    private class UpdateDataAction extends AbstractAction {
        public UpdateDataAction(String name, int mnemonic) {
            super(name);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            handleData(new File("Foobar.txt"));
        }
    }

    private static void createAndShowGui() {
        UpdateDataEg mainPanel = new UpdateDataEg();

        JFrame frame = new JFrame("UpdateDataEg");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

class Data {

}