-
August 12th, 2011, 02:47 PM
#1
Weird SwingWorker Bug HELP!
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
I'd rather not post the code unless I need to.
-
August 12th, 2011, 02:54 PM
#2
Re: Weird SwingWorker Bug HELP!
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)
WHY WOULD IT DO THIS???? WHY???? WHY??? WHY???
-
August 12th, 2011, 03:09 PM
#3
Re: Weird SwingWorker Bug HELP!
Even using the solution at the bottom of this page doesn't help:
http://bugs.sun.com/bugdatabase/view...bug_id=6826514
This bug is so freaking weird! There seems to be a pattern to it, BUT WHY??!?!??!
-
August 12th, 2011, 03:13 PM
#4
Re: Weird SwingWorker Bug HELP!
http://forums.oracle.com/forums/thre...rt=15&tstart=0
post on top of page seems to have a similar problem.... BUT THE THREAD WAS LOCKED GODDAMNIT!
-
August 12th, 2011, 03:28 PM
#5
Re: Weird SwingWorker Bug HELP!
Originally Posted by clcoulte
I'd rather not post the code unless I need to.
If you really want to solve your problem, take the time to create a SSCCE.
-
August 12th, 2011, 08:46 PM
#6
Re: Weird SwingWorker Bug HELP!
Heres an SSCCE though it may not be the simplest.
You may need to run it to see what I mean.
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; // 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() {
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) {
setProgress((100 * progNotRatioed) / maxProg);
}
tempData[i][j] = 1;
}
}
return tempData;
}
@Override
public void done() {
startButton.setEnabled(true);
taskOutput.append("Done!" + data + "\n");
}
}
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();
}
});
}
}
As is, with WIDTH = 198, we get null for data
if WIDTH is changed to 199, we get an object returned.
?
-
August 12th, 2011, 08:51 PM
#7
Re: Weird SwingWorker Bug HELP!
Sorry for sounding cross, I just see absolutely no reason why this should happen...
-
August 12th, 2011, 08:52 PM
#8
Re: Weird SwingWorker Bug HELP!
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....
-
August 12th, 2011, 09:01 PM
#9
Re: Weird SwingWorker Bug HELP!
I might just try using a single dimension int instead of the two dimensional and see if that gets me anywhere...
-
August 12th, 2011, 10:28 PM
#10
Re: Weird SwingWorker Bug HELP!
That was a good SSCCE.
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.)
-
August 12th, 2011, 10:37 PM
#11
Re: Weird SwingWorker Bug HELP!
I'll give you the fix I made if you want (1 line) but I figured I'd give you a chance to figure it out.
-
August 13th, 2011, 09:26 PM
#12
Re: Weird SwingWorker Bug HELP!
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:
Code:
doInBackground Start
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
Done Start
Done End
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
Code:
doInBackground Start
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
doInBackground End
Done Start
Done End
-
August 13th, 2011, 09:27 PM
#13
Re: Weird SwingWorker Bug HELP!
I really appreciate the help. Sorry if I'm being dense
-
August 13th, 2011, 09:32 PM
#14
Re: Weird SwingWorker Bug HELP!
This is from the SSCE:
Dimensions: 200, 198 (and down)
(incorrect)
Code:
getData start
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
done start
done end
Dimensions: 200, 199 (and up)
(seemingly correct)
Code:
getData start
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
getData end
done start
done end
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
-
August 14th, 2011, 08:58 AM
#15
Re: Weird SwingWorker Bug HELP!
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:
Code:
setProgress(Math.min((100 * progNotRatioed) / maxProg, 100));
I didn't figure out why your calculation goes past 100 or if that matters or not though.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|