Reputation: 645
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 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
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