I am trying to write a progress bar for an application that is downloading information before the GUI runs. Because this is such a long process to download and organize the information, I am wanting to inform the user of the progress. I decided on using a progress bar late in the game and, as such, a majority of the code is written and I'm trying to incorporate the progress bar into the code without a drastic re-working of the code. The following is the code for the progress bar. Currently, the progress bar comes up AFTER everything runs and the GUI pops up.
static class PopulatingCardsWorker extends SwingWorker<Void, Integer> {
JProgressBar jpb;
int max;
JLabel label;
public PopulatingCardsWorker(JProgressBar jpb, int maximum, JLabel label) {
this.jpb = jpb;
this.max = maximum;
this.label = label;
}
@Override
protected void process(List<Integer> chunks) {
int i = chunks.get(chunks.size()-1);
jpb.setValue(i); // The last value in this array is all we care about.
System.out.println(i);
label.setText("Loading " + i + " of " + max);
}
@Override
protected Void doInBackground() throws Exception {
for(int i = 0; i < max; i++) {
Thread.sleep(10); // Illustrating long-running code.
publish(i);
}
return null;
}
@Override
protected void done() {
try {
get();
JOptionPane.showMessageDialog(jpb.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
}
private static void go(int max) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel label = new JLabel("Loading...");
JProgressBar jpb = new JProgressBar();
jpb.setIndeterminate(false);
jpb.setMaximum(max);
panel.add(label);
panel.add(jpb);
frame.add(panel);
frame.pack();
frame.setSize(200,90);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new PopulatingCardsWorker(jpb, max, label).execute();
}
The program initially calls the GUI application and then runs the database acquisition code as shown below.
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MagicTheGatheringUI().setVisible(true);
}
});
}
public MagicTheGatheringUI() {
int i, size;
colorRefinementFilter = "selected";
try {
my_list=new CardDatabase();
my_list.sortByName(my_list.all_cards);
my_list.populateSubArrays();
size = my_list.all_cards.size();
for(i = 0; i < size; i++)
{
namesList.addElement(my_list.all_cards.get(i).name);
}
} catch(Exception e) {
System.out.println(e);
System.exit(0);
}
initComponents();
}
The swing worker is created during the creation of "my_list=new CardDatabase();". In that class, I have the swing worker and the process the swing worker is supposed to monitor.
I currently call swing worker in a method called "populate_cards()" and I use the following code to create the swing worker. The swing worker is supposed to monitor what's going on in the populate_cards() method. All of the data in the swing worker methods are just temporary until I better understand how to make it work the way I want it to.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
go(1000);
}
});
I believe the issue is that I'm calling the progress bar inside of the "invokeLater" method for the actual GUI.
I have looked at the following questions to try and solve my problem.
Can a progress bar be used in a class outside main?
and I have also looked at tutorials.