I have a SwingWorker which generates an int[][] into a variable local to the SwingWorker object in its doInBackground() method.
The done() method then assigns that int[][] to another variable.
For some reason doInBackground() assigns null to the SwingWorker local variable with certain dimensions.
int[900][891 (and down) ] gives me null
int[900][892 (and up) ] works fine (generates expected results)
int[800][792 (and down) ] gives me null
int[800][793 (and up) ] works fine
int[700][693 (and down) ] gives me null
int[700][694 (and up) ] works fine
etc....
int[708 (and up) ][700] gives me null
int[707 (and down) ] [700] works fine
etc....
The SwingWorker is NEVER canceled through my code.
The doInBackground() calls another local private thread to set the local int[][].
I've gone through the debugger in this thread and it never hits a breakpoint on any of the return statements inside it. It just seems to randomly return after a while of iterating through the temporary int[][] while generating values with a null.
I call setProgress() from within this method but I don't see why that would cause the method to return null and proceed to done() without me calling return null;
other than that its all pretty simple algebraic math being done
It seems as though it never hits the return statement for the doInBackground() method and goes straight to done() even though its not canceled whatsoever (isCanceled() == false)
I get more weird output when I set WIDTH = 100 or 150 with HEIGHT = 200
Task only reports 50% and 75% respectively....
Im going to check the debugger with these cases....
I generally use Eclipse to debug, but the SSCCE was so S that I just used notepad.
Here's the debugging I added:
Code:
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
public class ProgressBarDemo extends JPanel implements ActionListener,
PropertyChangeListener {
private JProgressBar progressBar;
private JButton startButton;
private JTextArea taskOutput;
private Task task;
// private static final int WIDTH = 200, HEIGHT = 198;
private static final int WIDTH = 200, HEIGHT = 694;
// Change HEIGHT to 694, expected result
class Task extends SwingWorker<Void, Void> {
private int[][] data;
@Override
public Void doInBackground() {
setProgress(0);
data = getData();
return null;
}
private int[][] getData() {
System.out.println("getData start");
int[][] tempData = new int[WIDTH][HEIGHT];
int maxProg = WIDTH * HEIGHT;
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
int progNotRatioed = WIDTH * i + j;
if ((100 * progNotRatioed) % maxProg == 0) {
System.out.println((100 * progNotRatioed) / maxProg);
setProgress((100 * progNotRatioed) / maxProg);
}
tempData[i][j] = 1;
}
}
System.out.println("getData end");
return tempData;
}
@Override
public void done() {
System.out.println("done start");
startButton.setEnabled(true);
taskOutput.append("Done!" + data + "\n");
System.out.println("done end");
}
}
public ProgressBarDemo() {
super(new BorderLayout());
// Create the demo's UI.
startButton = new JButton("Start");
startButton.setActionCommand("start");
startButton.addActionListener(this);
progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
taskOutput = new JTextArea(5, 20);
taskOutput.setMargin(new Insets(5, 5, 5, 5));
taskOutput.setEditable(false);
JPanel panel = new JPanel();
panel.add(startButton);
panel.add(progressBar);
add(panel, BorderLayout.PAGE_START);
add(new JScrollPane(taskOutput), BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
/**
* Invoked when the user presses the start button.
*/
public void actionPerformed(ActionEvent evt) {
startButton.setEnabled(false);
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
}
/**
* Invoked when task's progress property changes.
*/
public void propertyChange(PropertyChangeEvent evt) {
if ("progress" == evt.getPropertyName()) {
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
taskOutput.append(String.format("Completed %d%% of task.\n",
task.getProgress()));
}
}
/**
* Create the GUI and show it. As with all GUI code, this must run on the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("ProgressBarDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
JComponent newContentPane = new ProgressBarDemo();
newContentPane.setOpaque(true); // content panes must be opaque
frame.setContentPane(newContentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
After flipping back & forth between the 2 different height values & looking at the System.out.println's I added the fix became obvious (hint: I used a method from this class.)
I'm sorry, I really wish I could understand whats going on. Are you implying that there is something going wrong when I calculate the progress? Like imprecision between ints and doubles?
I think theres something weirder going on.
I added the println's in the same exact places in my original code and I'm getting this output:
The println for "doInBackground End" is never reached whatsoever and data just ends up being null.
This is for dimensions 200, 198
I'm having trouble repeating this in the SSCE though
This is the output for my original code with dimensions 200, 199
and then I also get weiiirdd results for some other dimensions, like it will repeat a progress number 3 times and/or stop at 25 % or 50 % depending on the dimensions... etc.
I really really appreciate you taking the time to help me though
Sorry for being secretive about it. Anyway, notice that on the bad one it goes up to 101. But apparently the setProgress is expecting values up to only 100 (like as in a percentage). It apparently doesn't like 101...maybe the underlying code is interpreting that as 1 for some reason. Anyway, the fix was to use Math.min to ensure that it doesn't go past 100:
Bookmarks