RMRiver
RMRiver

Reputation: 645

JFrame appears blank after the first time calling it

This JFrame the first time I call it when the application is running, works perfectly. But when I try to open a new file, the progress bar is meant to return to the screen. See the screen grabs to see how it should look at how it looks thereafter.

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;
}

This is how the progress bar and JFrame should look:

This is how the progress bar and JFrame should look.

This Is how the progress bar looks the second time:

This Is how the progress bar looks the second time

All code:

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;
}

}

Upvotes: 1

Views: 407

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285430

Without your posting a valid minimal example program, it's impossible for us to know with absolute surety the cause of your problem, the image suggests that it's a Swing threading problem, that you've got long-running code, probably here:

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

that is blocking the Swing event thread, and that this is causing the Swing GUI not to paint itself.

If so, the solution is to improve your code so that it respects the Swing event thread, so that long-running code is run in a background thread such as via a SwingWorker.

Other issues: that window you display looks to be a "dependent" window and not a main application window. If so, it should not be created as a JFrame but rather as a JDialog, either modal or non-modal depending on your needs.

Also -- why does it work the first time? Likely the first time, the code above is not run on the Swing event thread, the EDT, while the second time that code is called, it is in fact run on the EDT. You can test this by calling SwingUtilities.isEventDispatchThread() and printing out the result. e.g.,

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

For example:

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 {

}

Upvotes: 2

Related Questions