这个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的外观:
这是第二次进度条的显示方式:
所有代码:
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;
}
}
答案 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 {
}