I'm using SwingWorker and
It perfectly updates JProgressBar WHEN the process is not too heavy (for example "Trames" list containing 62 elements)
It doesn't update JProgressBar when the process is heavy (I tested with 100k elements, it'll finally works with 2M+ elems)
Below my ProgressWorker class
#Override
protected Object doInBackground() throws Exception {
// TODO Auto-generated method stub
// here process i skipped
for (Trame t : trames) {
float progress = (float)FileRW.tramescounter/FileRW.maxtrames;
progress = progress*100;
int p = (int) progress;
setProgress(p);
System.out.println(getProgress()+"+p"+" ---- progress"+p+" ---- double"+progress);
Thread.sleep(25);
FileRW.tramescounter++;
// here process i skipped
}
// here process i skipped
return null;
}
Besides, my controller class:
ProgressWorker pw = new ProgressWorker();
pw.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name.equals("progress")) {
int progress = (int) evt.getNewValue();
Vue.bar.setValue(progress);
Vue.bar.repaint();
} else if (name.equals("state")) {
SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
switch (state) {
case DONE:
Vue.lastButton.setEnabled(true);
if (Vue.check.isSelected()) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.open(new File(Constants.FICHIER_LOG2));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Vue.filesInDirectory = null;
Vue.fileLabel.setText(Constants.PAN1_LABEL);
break;
default:
break;
}
}
}
});
pw.execute();
There's a runnable example (based on your out-of-context code) which works, so my guess is, it's not the SwingWorker which is at fault, but some part of the code you're not sharing.
Consider providing a Minimal, Complete, and Verifiable example which demonstrates your problem, until you do, this is about all the help we can possible give you
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import static javax.swing.SwingWorker.StateValue.DONE;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JProgressBar pb = new JProgressBar(0, 100);
public TestPane() {
setLayout(new GridBagLayout());
add(pb);
BadWorker pw = new BadWorker();
pw.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name.equals("progress")) {
int progress = (int) evt.getNewValue();
pb.setValue(progress);
} else if (name.equals("state")) {
SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
switch (state) {
case DONE:
System.out.println("All done where");
break;
}
}
}
});
pw.execute();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class BadWorker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
int count = 0;
int max = 10000;
do {
count++;
float progress = (float) count / max;
progress = progress * 100;
int p = (int) progress;
setProgress(p);
System.out.println(getProgress() + "+p" + " ---- progress" + p + " ---- double" + progress);
Thread.sleep(5);
// here process i skipped
} while (getProgress() < 100);
// here process i skipped
return null;
}
}
}
Ok nevermind the problem wasn't the one I expected
Just inside the first part of code I skipped I wrote
Vue.bar.setMaximum(trames.size());
Further,
float progress = (float)FileRW.tramescounter/FileRW.maxtrames;
progress = progress*100;
int p = (int) progress;
setProgress(p);
And in controller class
Vue.bar.setValue(progress);
But progress value set in ProgressWorker is from 0 to 100
My max ProgressBar value was 100K but the 0 < progression value <100,
It was normal that it didn't progress
Related
I have made a very simple code to show it here, i have a button that should show a JDialog to check the progress status, i am using the invoke late to go through EDT and my loop isn't in the run method, so why isn't my bar updating ?
here is the code
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class JBarEx extends JFrame {
private JTextField progStatus = new JTextField("Undefined");
private JButton dialogBtn = new JButton("Show Progression dialog");
final JDialog dlg = new JDialog((JFrame) null, "prog Title", false);
final JProgressBar dpb = new JProgressBar(0, 100);
public JBarEx() {
JPanel pan = new JPanel();
dialogBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
showProgress();
}
});
progStatus.setEditable(false);
pan.add(progStatus);
pan.add(dialogBtn);
setContentPane(pan);
this.setSize(200, 100);
setVisible(true);
}
public void showProgress() {
dlg.add(BorderLayout.CENTER, dpb);
dlg.add(BorderLayout.NORTH, new JLabel("prog message"));
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setSize(300, 75);
dlg.setLocationRelativeTo(null);
dlg.setVisible(true);
for (int i = 0; i < 100; i++) {
final int ii = i;
try {
Thread.sleep(25);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
updateBar(ii);
}
});
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void updateBar(int newValue) {
dpb.setValue(newValue);
}
public static void main(String[] args) {
JBarEx jbx = new JBarEx();
}
}
Your showProgress method is being executed within the context of the Event Dispatching Thread. The EDT is responsible for, amongst other things, processing paint requests. This means that so long as your for-loop is executing, the EDT can not process any new paint requests (or handle the invokeLater events either) as it is blocking the EDT.
While there are any number of possible ways to solve the problem, based on your code example, the simplest would be to use a SwingWorker.
It has the capacity to allow your to execute the long running task the a background thread (freeing up the EDT), but also allows you means for publishing updates (if required) so that they can be processed in the EDT and also provides handy progress notification.
For example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class SwingWorkerProgress {
public static void main(String[] args) {
new SwingWorkerProgress();
}
public SwingWorkerProgress() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JProgressBar pbProgress;
private JButton start;
public TestPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
pbProgress = new JProgressBar();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
add(pbProgress, gbc);
start = new JButton("Start");
gbc.gridy++;
add(start, gbc);
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
start.setEnabled(false);
ProgressWorker pw = new ProgressWorker();
pw.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name.equals("progress")) {
int progress = (int) evt.getNewValue();
pbProgress.setValue(progress);
repaint();
} else if (name.equals("state")) {
SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
switch (state) {
case DONE:
start.setEnabled(true);
break;
}
}
}
});
pw.execute();
}
});
}
}
public class ProgressWorker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
for (int i = 0; i < 100; i++) {
setProgress(i);
try {
Thread.sleep(25);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
}
Check out Concurrency in Swing for more details
Even if you fix the loop as others have pointed out, you'd still block the event dispatch thread. The for loop is run in showProgress() which is called from an event listener. The updates are pushed to the event queue, but that does not get processed until the loop has completed.
Use a Swing Timer instead. Something like this:
Timer timer = new Timer(25, new ActionListener() {
private int position;
#Override
public void actionPerformed(ActionEvent e) {
position++;
if (position < lastPosition) {
updateBar(position);
} else {
((Timer) e.getSource).stop();
}
}
});
timer.start();
where lastPosition would be the state where you want the progress bar to stop.
Unrelated to that bug, but a bug still, you should not create swing components outside the event dispatch thread. It's best to do it right from the start:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JBarEx jbx = new JBarEx();
}
});
}
for (int i = 0; i < 0; i++) {
You will never enter this code so will never call the updateBar(..) method
i needs to be greater than 0 in this case. If it is 1 then updateBar will be called once, if 2 then updateBar will be called twice etc
Also rather than doing
Thread.sleep(25);
take a look at java executors as these will help with your scheduling and remove the need for the sleep
I wanted to make a Glass Panel that contain a JPanel with white background, border and the msg "please wait".
Here is the code example:
JLabel glassLabel = new JLabel("Please wait");
FadingPanel msg = new FadingPanel();
glassLabel.setFont(new Font("Dialog", Font.BOLD, 26));
msg.setLayout(new BorderLayout());
msg.add(glassLabel,BorderLayout.NORTH);
msg.setBackground(Color.white);
msg.setFont(UIManager.getFont("Table.font").deriveFont(24f));
msg.setBorder(new CompoundBorder(new TitledBorder(""),
new EmptyBorder(20,20,20,20)));
It will fade in and out while waiting for the query.
the problem is that I am getting a bad result.
need help
the other is that none of them show it with glass panel
Animating the opacity state of a glassPane is no different from animating the state of any Swing component, after all, the glassPane is just another component.
one is that the Timer system doesn't know if the start function started and it keeps the panel hanging on because it closing it before fading the panel and then before it shows it and then it dont try to close it again
This is more about your own internal state management. The panel shouldn't care, it should just be responding to the request to change opacity level, forward or backwards
What you should have, is some kind of "engine" which can provide events when certain states are achieved, at which time, you make decisions about what should be done, removing the functionality from the "panel" itself.
Theory TL;DR
Okay, first, some theory.
Animation...
Animation is the illusion of change over time. In your case, you're moving from 0 to 1 and back again over a specified period of time. This is commonly known as "linear progression/animation". Most naive animation implementations will simple add a constant delta to a value and keep doing so until a desired state is reached. This is naive because not all systems are equal. Some will be able to achieve the desired state faster than others, making the animation uneven and providing a poor user experience.
Instead, you should be focused on perform a operation over a fixed period of time, calculating the required value as fast as the system will allow. This allows the animation to "drop" frames as required based on the system's capabilities. This is commonly known as "duration based animation".
This approach is much more powerful, as it allows you to play around with the speed of the animation in a very simply way. It also allows you do some very advanced operations, like easement, which wouldn't be easily achievable through a linear progression.
Swing and animation...
Swing is SINGLE threaded. This means you can't perform blocking or long running operations within the context of the Event Dispatching Thread.
Swing is also NOT thread safe. This means you shouldn't update the UI (or any state the UI depends on) from outside the context of the EDT.
For animation, what you need is some way to post, fast, repetitive, events onto the EDT, which will allow you to make changes to the UI safely. For this, the most common tool is a Swing Timer...
The Framework
So based on that, what we need is some kind of "engine", which given a "range" and a "duration" can notify us of "ticks" on a regular bases from which we can calculate the progression that the animation has played, and calculate the value we should use based on our inputs ... simple ...
I, personally, prefer to use an animation library, but the simple framework presented in the examples basically abstracts all these concepts into a re-usable framework.
Make it so...
nb: I ran out of room, so the underlying framework is included in the main example
Okay, that's all nice and fluffy, but how does this actually help us. Essentially, the idea of the above is to abstract common functionality out and make it re-usable (and yes, I actually do use it, a lot)
What we now need, is a component which can actually use it, something like...
public interface FaderListener {
public void fadeDidComplete(FadePane pane);
}
public class FadePane extends JPanel {
private double alpha = 1;
private boolean fadingIn = true;
private DoubleAnimatable animatable;
private Duration duration = Duration.ofSeconds(5);
private List<FaderListener> listeners = new ArrayList<>(5);
public FadePane() {
setOpaque(false);
}
public void addFadeListener(FaderListener listener) {
listeners.add(listener);
}
public void removeFadeListener(FaderListener listener) {
listeners.remove(listener);
}
public boolean isFadingIn() {
return fadingIn;
}
public double getAlpha() {
return alpha;
}
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive((float)getAlpha()));
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
super.paint(g2d);
g2d.dispose();
}
protected void fadeTo(double to) {
double currentAlpha = getAlpha();
if (animatable != null) {
animatable.stop();
animatable = null;
}
if (currentAlpha == to) {
fadeDidComplete();
return;
}
DoubleRange animationRange = new DoubleRange(currentAlpha, to);
double maxFrom = to == 1 ? 1 : 0;
double maxTo = to == 1 ? 0 : 1;
DoubleRange maxRange = new DoubleRange(maxFrom, maxTo);
animatable = new DoubleAnimatable(animationRange, maxRange, duration, new AnimatableListener<Double>() {
#Override
public void animationChanged(Animatable<Double> animatable) {
alpha = animatable.getValue();
repaint();
}
}, new AnimatableLifeCycleListenerAdapter<Double>() {
#Override
public void animationCompleted(Animatable<Double> animatable) {
fadeDidComplete();
}
});
Animator.INSTANCE.add(animatable);
}
public void fadeIn() {
fadingIn = true;
fadeTo(1);
}
public void fadeOut() {
fadingIn = false;
fadeTo(0);
}
protected void fadeDidComplete() {
for (FaderListener listener : listeners) {
listener.fadeDidComplete(this);
}
}
}
Okay, this is a pretty simple concept. It's a JPanel which has a alpha property which changes the opacity level of the component - basically, this is all faked, as Swing only support opaque and transparent components, not translucent components. So we set the component to be transparent and manually paint the background ourselves.
The component exposes two methods, fadeIn and fadeOut and supports a FaderListener which can be used to notify interested parties that the fade operation has been completed
Runnable example...
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
setLayout(new BorderLayout());
FadePane pane = new FadePane();
pane.setLayout(new GridBagLayout());
pane.add(new JLabel("Look ma, no hands"));
add(pane);
JButton btn = new JButton("Switch");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
btn.setEnabled(false);
if (pane.isFadingIn()) {
pane.fadeOut();
} else {
pane.fadeIn();
}
}
});
add(btn, BorderLayout.SOUTH);
pane.addFadeListener(new FaderListener() {
#Override
public void fadeDidComplete(FadePane pane) {
btn.setEnabled(true);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public interface FaderListener {
public void fadeDidComplete(FadePane pane);
}
public class FadePane extends JPanel {
private double alpha = 1;
private boolean fadingIn = true;
private DoubleAnimatable animatable;
private Duration duration = Duration.ofSeconds(5);
private List<FaderListener> listeners = new ArrayList<>(5);
public FadePane() {
setOpaque(false);
}
public void addFadeListener(FaderListener listener) {
listeners.add(listener);
}
public void removeFadeListener(FaderListener listener) {
listeners.remove(listener);
}
public boolean isFadingIn() {
return fadingIn;
}
public double getAlpha() {
return alpha;
}
public void setFaddedOut() {
alpha = 0;
fadingIn = false;
}
public void setFaddedIn() {
alpha = 1;
fadingIn = true;
}
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive((float)getAlpha()));
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
super.paint(g2d);
g2d.dispose();
}
protected void fadeTo(double to) {
double currentAlpha = getAlpha();
if (animatable != null) {
animatable.stop();
animatable = null;
}
if (currentAlpha == to) {
fadeDidComplete();
return;
}
DoubleRange animationRange = new DoubleRange(currentAlpha, to);
double maxFrom = to == 1 ? 1 : 0;
double maxTo = to == 1 ? 0 : 1;
DoubleRange maxRange = new DoubleRange(maxFrom, maxTo);
animatable = new DoubleAnimatable(animationRange, maxRange, duration, new AnimatableListener<Double>() {
#Override
public void animationChanged(Animatable<Double> animatable) {
alpha = animatable.getValue();
repaint();
}
}, new AnimatableLifeCycleListenerAdapter<Double>() {
#Override
public void animationCompleted(Animatable<Double> animatable) {
fadeDidComplete();
}
});
Animator.INSTANCE.add(animatable);
}
public void fadeIn() {
fadingIn = true;
fadeTo(1);
}
public void fadeOut() {
fadingIn = false;
fadeTo(0);
}
protected void fadeDidComplete() {
for (FaderListener listener : listeners) {
listener.fadeDidComplete(this);
}
}
}
public class DoubleAnimatable extends AbstractAnimatable<Double> {
public DoubleAnimatable(DoubleRange animationRange, DoubleRange maxRange, Duration duration, AnimatableListener<Double> listener, AnimatableLifeCycleListener<Double> lifeCycleListener) {
super(animationRange, duration, listener, lifeCycleListener);
double maxDistance = maxRange.getDistance();
double aniDistance = animationRange.getDistance();
double progress = Math.min(100, Math.max(0, Math.abs(aniDistance / maxDistance)));
Duration remainingDuration = Duration.ofMillis((long) (duration.toMillis() * progress));
setDuration(remainingDuration);
}
}
public interface AnimatableListener<T> {
public void animationChanged(Animatable<T> animatable);
}
public interface AnimatableLifeCycleListener<T> {
public void animationStopped(Animatable<T> animatable);
public void animationCompleted(Animatable<T> animatable);
public void animationStarted(Animatable<T> animatable);
public void animationPaused(Animatable<T> animatable);
}
public class AnimatableLifeCycleListenerAdapter<T> implements AnimatableLifeCycleListener<T> {
#Override
public void animationStopped(Animatable<T> animatable) {
}
#Override
public void animationCompleted(Animatable<T> animatable) {
}
#Override
public void animationStarted(Animatable<T> animatable) {
}
#Override
public void animationPaused(Animatable<T> animatable) {
}
}
public abstract class AbstractAnimatable<T> implements Animatable<T> {
private Range<T> range;
private LocalDateTime startTime;
private Duration duration = Duration.ofSeconds(5);
private T value;
private AnimatableListener<T> animatableListener;
private AnimatableLifeCycleListener<T> lifeCycleListener;
// private Easement easement;
private double rawOffset;
public AbstractAnimatable(Range<T> range, Duration duration, AnimatableListener<T> listener) {
this.range = range;
this.value = range.getFrom();
this.animatableListener = listener;
}
public AbstractAnimatable(Range<T> range, Duration duration, AnimatableListener<T> listener, AnimatableLifeCycleListener<T> lifeCycleListener) {
this(range, duration, listener);
this.lifeCycleListener = lifeCycleListener;
}
// public AbstractAnimatable(Range<T> range, Duration duration, Easement easement, AnimatableListener<T> listener) {
// this(range, duration, listener);
// this.easement = easement;
// }
//
// public AbstractAnimatable(Range<T> range, Duration duration, Easement easement, AnimatableListener<T> listener, AnimatableLifeCycleListener<T> lifeCycleListener) {
// this(range, duration, easement, listener);
// this.lifeCycleListener = lifeCycleListener;
// }
//
// public void setEasement(Easement easement) {
// this.easement = easement;
// }
//
// #Override
// public Easement getEasement() {
// return easement;
// }
public Duration getDuration() {
return duration;
}
public Range<T> getRange() {
return range;
}
public void setRange(Range<T> range) {
this.range = range;
}
#Override
public T getValue() {
return value;
}
protected void setDuration(Duration duration) {
this.duration = duration;
}
public double getCurrentProgress(double rawProgress) {
double progress = Math.min(1.0, Math.max(0.0, getRawProgress()));
// Easement easement = getEasement();
// if (easement != null) {
// progress = easement.interpolate(progress);
// }
return Math.min(1.0, Math.max(0.0, progress));
}
public double getRawProgress() {
if (startTime == null) {
return 0.0;
}
Duration duration = getDuration();
Duration runningTime = Duration.between(startTime, LocalDateTime.now());
double progress = rawOffset + (runningTime.toMillis() / (double) duration.toMillis());
return Math.min(1.0, Math.max(0.0, progress));
}
#Override
public void tick() {
if (startTime == null) {
startTime = LocalDateTime.now();
fireAnimationStarted();
}
double rawProgress = getRawProgress();
double progress = getCurrentProgress(rawProgress);
if (rawProgress >= 1.0) {
progress = 1.0;
}
value = getRange().valueAt(progress);
fireAnimationChanged();
if (rawProgress >= 1.0) {
fireAnimationCompleted();
}
}
#Override
public void start() {
if (startTime != null) {
// Restart?
return;
}
Animator.INSTANCE.add(this);
}
#Override
public void stop() {
stopWithNotification(true);
}
#Override
public void pause() {
rawOffset += getRawProgress();
stopWithNotification(false);
double remainingProgress = 1.0 - rawOffset;
Duration remainingTime = getDuration().minusMillis((long) remainingProgress);
setDuration(remainingTime);
lifeCycleListener.animationStopped(this);
}
protected void fireAnimationChanged() {
if (animatableListener == null) {
return;
}
animatableListener.animationChanged(this);
}
protected void fireAnimationCompleted() {
stopWithNotification(false);
if (lifeCycleListener == null) {
return;
}
lifeCycleListener.animationCompleted(this);
}
protected void fireAnimationStarted() {
if (lifeCycleListener == null) {
return;
}
lifeCycleListener.animationStarted(this);
}
protected void fireAnimationPaused() {
if (lifeCycleListener == null) {
return;
}
lifeCycleListener.animationPaused(this);
}
protected void stopWithNotification(boolean notify) {
Animator.INSTANCE.remove(this);
startTime = null;
if (notify) {
if (lifeCycleListener == null) {
return;
}
lifeCycleListener.animationStopped(this);
}
}
}
public interface Animatable<T> {
public Range<T> getRange();
public T getValue();
public void tick();
public Duration getDuration();
//public Easement getEasement();
// Wondering if these should be part of a secondary interface
// Provide a "self managed" unit of work
public void start();
public void stop();
public void pause();
}
public abstract class Range<T> {
private T from;
private T to;
public Range(T from, T to) {
this.from = from;
this.to = to;
}
public T getFrom() {
return from;
}
public T getTo() {
return to;
}
#Override
public String toString() {
return "From " + getFrom() + " to " + getTo();
}
public abstract T valueAt(double progress);
}
public class DoubleRange extends Range<Double> {
public DoubleRange(Double from, Double to) {
super(from, to);
}
public Double getDistance() {
return getTo() - getFrom();
}
#Override
public Double valueAt(double progress) {
double distance = getDistance();
double value = distance * progress;
value += getFrom();
return value;
}
}
public enum Animator {
INSTANCE;
private Timer timer;
private List<Animatable> properies;
private Animator() {
properies = new ArrayList<>(5);
timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
List<Animatable> copy = new ArrayList<>(properies);
Iterator<Animatable> it = copy.iterator();
while (it.hasNext()) {
Animatable ap = it.next();
ap.tick();
}
if (properies.isEmpty()) {
timer.stop();
}
}
});
}
public void add(Animatable ap) {
properies.add(ap);
timer.start();
}
protected void removeAll(List<Animatable> completed) {
properies.removeAll(completed);
}
public void remove(Animatable ap) {
properies.remove(ap);
if (properies.isEmpty()) {
timer.stop();
}
}
}
}
But it's not a glassPane
... ok, as I said, a glassPane is just another component
This is a simple example which makes use of the frame's glassPane and will, when the panel is faded out, reset the glassPane to a default component
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
JButton btn = new JButton("Switch");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window window = SwingUtilities.getWindowAncestor(TestPane.this);
if (!(window instanceof JFrame)) {
System.out.println("Not out frame");
return;
}
JFrame frame = (JFrame) window;
FadePane pane = new FadePane();
pane.setLayout(new BorderLayout());
pane.add(new JLabel("All your base are belong to us"));
pane.setFaddedOut();
pane.addFadeListener(new FaderListener() {
#Override
public void fadeDidComplete(FadePane pane) {
System.out.println("Completed");
if (pane.getAlpha() == 1) {
System.out.println("Fade out");
pane.fadeOut();
} else {
System.out.println("Remove glasspane");
frame.setGlassPane(new JPanel());
}
}
});
frame.setGlassPane(pane);
System.out.println("Fade in");
pane.setVisible(true);
pane.fadeIn();
}
});
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
nb: The required classes are in the previous example
Consider using JDialog container. When it is undecorated, you can change its opacity:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class FadeDialog extends JDialog {
private float alfa = 1;
private JLabel label;
private boolean isFadeIn = true;
private JButton fadeIn, fadeOut;
FadeDialog() {
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setLocation(new Point(300, 300));
getContentPane().setLayout(new BorderLayout(5,0));
setUndecorated(true); //opacity supported for undecorated JDialogs
JButton close = new JButton("Close");
close.addActionListener(e -> dispose());
getContentPane().add(close, BorderLayout.PAGE_END);
getContentPane().add(new ContentPane(), BorderLayout.CENTER);
pack();
setVisible(true);
Timer timer = new Timer(2000, e -> fade());//endless fade-in-out loop
timer.setInitialDelay(100);
timer.start();
}
void fade() {
alfa = isFadeIn ? alfa + 0.1f : alfa -0.1f;
if(alfa <=0 ) {
alfa = 0; isFadeIn = true;
}else if(alfa >= 1) {
alfa = 1; isFadeIn = false;
}
fadeIn.setEnabled(! isFadeIn); fadeOut.setEnabled(isFadeIn);
label.setText("Alfa is " + alfa);
setOpacity(alfa); //set JDialog opacity
}
class ContentPane extends JPanel {
ContentPane() {
setPreferredSize(new Dimension(200, 100));
setLayout(new BorderLayout());
fadeIn = new JButton("Fade In");
fadeIn.addActionListener(e -> isFadeIn = true);
add(fadeIn, BorderLayout.PAGE_START);
label = new JLabel("Alfa is " + alfa);
add(label, BorderLayout.CENTER);
fadeOut = new JButton("Fade Out");
fadeOut.addActionListener(e -> isFadeIn = false);
add(fadeOut, BorderLayout.PAGE_END);
}
}
public static void main(String[] args) {
new FadeDialog();
}
}
We are using foxtrot package for stop freeze the swing application.
But in this below code it make a deadlock.
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import foxtrot.Task;
import foxtrot.Worker;
public class FoxtrotExample extends JFrame {
public static void main(String[] args) {
FoxtrotExample example = new FoxtrotExample();
example.setVisible(true);
}
boolean st = true;
public FoxtrotExample() {
super("Foxtrot Example");
final JButton button = new JButton("Take a nap !");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Start..");
button.setText("Sleeping...");
String text = null;
try {
text = (String) Worker.post(new Task() {
public Object run() throws Exception {
System.out.println("Inside Worker 1");
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
System.out.println("Inside invokeLater");
Worker.post(new Task() {
#Override
public Object run()
throws Exception {
System.out.println("Inside Worker 2");
st = false;
return null;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
while (st) {
System.out.println("Inside the loop..");
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
return "Slept !";
}
});
} catch (Exception x) {
}
button.setText(text);
System.out.println("Finished.....");
}
});
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
Container c = getContentPane();
c.setLayout(new GridBagLayout());
c.add(button);
setSize(300, 200);
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
Dimension size = getSize();
int x = (screen.width - size.width) >> 1;
int y = (screen.height - size.height) >> 1;
setLocation(x, y);
}
}
If use ConcurrentWorker this will work fine.Can any one explane this.
I am bit confuse how EDT behave here ?
This is the result of my program.
Start 1st worker
In the loop
Start invoke later
In the loop
In the loop
In the loop
In the loop
......
It start the 1st worker.Then part of the code is in invokeLater.So request is enqued in the event queue and start the loop.Later execute the invokeLater but not execute the 2nd worker because first worker still doing some work.Since worker are ruining one after another and it runs on a single worker queue 2nd worker cannot execute and deadlock comes.
Thanks to MadProgrammer i understood this.Hope this is correct.
I have a some class for downloading a big files from a web sites and displaying a process with jProgressBar.
I am using a SwingWorker class and the method doInBackground. It works fine, but when size of downloaded file > 20mb, i am getting a java.lang.IllegalArgumentException: the value should be from 0 to 100. What am i doing wrong? Please, help me! My piece of code:
#Override
protected Void doInBackground() throws Exception {
URL url = new URL(site);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int filesize = connection.getContentLength();
int totalDataRead = 0;
try (java.io.BufferedInputStream in = new java.io.BufferedInputStream(
connection.getInputStream())) {
java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
try (java.io.BufferedOutputStream bout = new BufferedOutputStream(
fos, 1024)) {
byte[] data = new byte[1024];
int i;
while ((i = in.read(data, 0, 1024)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
int percent = (totalDataRead * 100) / filesize;
setProgress(percent);
}
}
}
return null;
}
}
Having played around with your calculations, this...
int percent = (totalDataRead * 100) / filesize;
Just looks wrong to me (it might just be my pathetic math brain), but out of 40mb at around 20.48mb (or 51%), it reverts to a negative number (-51%)
How ever, if I use
int percent = Math.round(((float)count / (float)range) * 100f);
It works just fine.
Also, I'd consider making filesize and totalDataRead long instead of int, but that's just me.
And a runnable example which I used to test it with...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JProgressBar pb;
public TestPane() {
pb = new JProgressBar();
setLayout(new GridBagLayout());
add(pb);
SwingWorker worker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
int range = 40 * (1024 * 1024);
for (int count = 0; count < range; count += 1024) {
int percent = Math.round(((float)count / (float)range) * 100f);
setProgress(percent);
Thread.sleep(1);
}
return null;
}
};
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (null != evt.getPropertyName()) {
switch (evt.getPropertyName()) {
case "progress":
pb.setValue(worker.getProgress());
break;
}
}
}
});
worker.execute();
}
}
}
I have two SwingWorker class: FileLineCounterThread and FileDivisionThread
I will execute the two threads. When the lines counting thread finishes, it will pass the result to File Division thread.
I do not have an idea on how to pass the result to started thread.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class ExecutorAndSwingWorker2 {
private JFrame frame = new JFrame();
private JButton button1;
private JButton button2;
private JButton button3;
private JButton button4;
private JPanel buttonPanel = new JPanel();
private Executor executor = Executors.newCachedThreadPool();
private javax.swing.Timer timer1;
private javax.swing.Timer timer2;
private javax.swing.Timer timer3;
private javax.swing.Timer timer4;
private Random random = new Random();
public ExecutorAndSwingWorker2() {
button1 = new JButton(" Executor + SwingWorker Thread No.1 ");
button1.setFocusable(false);
button2 = new JButton(" Executor + SwingWorker Thread No.2 ");
button3 = new JButton(" Executor + SwingWorker Thread No.3 ");
button4 = new JButton(" Executor + SwingWorker Thread No.4 ");
buttonPanel = new JPanel();
buttonPanel.setBorder(new EmptyBorder(15, 15, 15, 15));
buttonPanel.setLayout(new GridLayout(2, 2, 20, 20));
buttonPanel.add(button1);
buttonPanel.add(button2);
buttonPanel.add(button3);
buttonPanel.add(button4);
frame.setTitle("Shaking Button Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(buttonPanel);
frame.setPreferredSize(new Dimension(700, 170));
frame.setLocation(150, 100);
frame.pack();
frame.setVisible(true);
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT
}
private void startButton1() {
System.out.println("Starting long Thread == startButton1()");
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
}
}
private void startButton2() {
System.out.println("Starting long Thread == startButton2()");
try {
Thread.sleep(17500);
} catch (InterruptedException ex) {
}
}
private void startButton3() {
System.out.println("Starting long Thread == startButton3()");
try {
Thread.sleep(12500);
} catch (InterruptedException ex) {
}
}
private void startButton4() {
System.out.println("Starting long Thread == startButton4()");
try {
Thread.sleep(20000);
} catch (InterruptedException ex) {
}
}
private void colorAction1() {
timer1 = new Timer(1000, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button1.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button1.validate();
button1.repaint();
}
});
}
});
timer1.setDelay(500);
timer1.setRepeats(true);
timer1.start();
}
private void colorAction2() {
timer2 = new Timer(1200, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button2.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button2.validate();
button2.repaint();
}
});
}
});
timer2.setDelay(500);
timer2.setRepeats(true);
timer2.start();
}
private void colorAction3() {
timer3 = new Timer(1400, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button3.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button3.validate();
button3.repaint();
}
});
}
});
timer3.setDelay(500);
timer3.setRepeats(true);
timer3.start();
}
private void colorAction4() {
timer4 = new Timer(1600, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
random = new Random();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
button4.setBackground(new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)));
button4.validate();
button4.repaint();
}
});
}
});
timer4.setDelay(500);
timer4.setRepeats(true);
timer4.start();
}
private void endButton1() {
timer1.stop();
button1.setBackground(null);
System.out.println("Long Thread Ends == startButton1()");
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton3")); // non on EDT
}
private void endButton2() {
timer2.stop();
button2.setBackground(null);
System.out.println("Long Thread Ends == startButton2()");
}
private void endButton3() {
timer3.stop();
button3.setBackground(null);
System.out.println("Long Thread Ends == startButton3()");
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton2")); // non on EDT
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton4")); // non on EDT
}
private void endButton4() {
timer4.stop();
button4.setBackground(null);
System.out.println("Long Thread Ends == startButton4()");
executor.execute(new ExecutorAndSwingWorker2.MyTask("startButton1")); // non on EDT
}
private class MyTask extends SwingWorker<Void, Integer> {
private String str;
private String namePr;
private JDialog dialog = new JDialog();
MyTask(String str) {
this.str = str;
addPropertyChangeListener(new SwingWorkerCompletionWaiter(dialog, str, namePr));
}
#Override
protected Void doInBackground() throws Exception {
if (str.equals("startButton1")) {
colorAction1();
startButton1();
} else if (str.equals("startButton2")) {
colorAction2();
startButton2();
} else if (str.equals("startButton3")) {
colorAction3();
startButton3();
} else if (str.equals("startButton4")) {
colorAction4();
startButton4();
}
return null;
}
#Override
protected void process(List<Integer> progress) {
System.out.println(str + " " + progress.get(progress.size() - 1));
}
#Override
protected void done() {
if (str.equals("startButton1")) {
endButton1();
} else if (str.equals("startButton2")) {
endButton2();
} else if (str.equals("startButton3")) {
endButton3();
} else if (str.equals("startButton4")) {
endButton4();
}
}
}
private class SwingWorkerCompletionWaiter implements PropertyChangeListener {
private JDialog dialog;
private String str;
private String namePr;
SwingWorkerCompletionWaiter(JDialog dialog, String str, String namePr) {
this.dialog = dialog;
this.str = str;
this.namePr = namePr;
}
#Override
public void propertyChange(PropertyChangeEvent event) {
if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) {
System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else {
System.out.println("Thread Status with Name :" + str + ", Something wrong happends ");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ExecutorAndSwingWorker2 executorAndSwingWorker = new ExecutorAndSwingWorker2();
}
});
}
}
SwingWorker.execute() is buggy and will only execute tasks serially. Use ExecutorService.execute() for concurrency:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RunnableFuture;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
public class MyFrame extends JFrame implements ActionListener {
/**
* Test Driver
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame frame = new MyFrame("Swing Concurrency Test");
frame.setVisible(true);
}
});
}
/**
* Thread Executor
* (must be explicitly shutdown, see WindowAdapter below)
*/
private final ExecutorService exec = Executors.newFixedThreadPool(2);
/**
* Button action
*/
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
textArea.append("\nStarting both tasks...\n");
// start both tasks, pass a reference to outer task
FileLineCounterThread counterTask = new FileLineCounterThread();
exec.execute(counterTask);
FileDivisionThread divisionTask = new FileDivisionThread(counterTask);
exec.execute(divisionTask);
}
/**
* Counter task
*/
private class FileLineCounterThread extends SwingWorker<Long, String> {
private String template = "[FileLineCounterThread] %s\n";
#Override
protected Long doInBackground() throws Exception {
// do some work
publish("started...");
Thread.sleep(10000);
// return the result
return 42L;
}
#Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textArea.append(String.format(template, chunk));
}
}
#Override
protected void done() {
try {
textArea.append(String.format(
template, "complete. Counted: " + get()));
}
catch (Exception e) {
// catch any exceptions thrown during execution
e.printStackTrace();
}
}
}
/**
* File Division task
*/
private class FileDivisionThread extends SwingWorker<String, String> {
private RunnableFuture<Long> counterTask;
private String template = " [FileDivisionThread] %s\n";
public FileDivisionThread(RunnableFuture<Long> counterTask) {
this.counterTask = counterTask;
}
#Override
protected String doInBackground() throws Exception {
// do some initial work
publish("started...");
Thread.sleep(2000);
// wait for other task to complete and get result
publish("Waiting for line counter to finish...");
long numLines = counterTask.get();
publish("Line count received: " + numLines);
// do the rest of the work and return result
Thread.sleep(5000);
return "complete.";
}
#Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textArea.append(String.format(template, chunk));
}
}
#Override
protected void done() {
try {
textArea.append(String.format(template, get()));
button.setEnabled(true);
}
catch (Exception e) {
// catch any exceptions thrown during execution
e.printStackTrace();
}
}
}
/////////////////////////
//// GUI Boilerplate ////
/////////////////////////
private JScrollPane scroller = new JScrollPane();
private JTextArea textArea = new JTextArea();
private JButton button = new JButton("Start");
public MyFrame(String windowTitle) {
super(windowTitle);
initComponents();
}
private void initComponents() {
addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
exec.shutdownNow();
System.exit(0);
}
});
button = new JButton("Start");
button.addActionListener(this);
textArea = new JTextArea();
textArea.setColumns(35);
textArea.setRows(15);
scroller.setViewportView(textArea);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.insets = new Insets(10, 0, 0, 0);
getContentPane().add(button, gridBagConstraints);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new Insets(10, 10, 10, 10);
getContentPane().add(scroller, gridBagConstraints);
pack();
}
}
PipedReader/Writer for character data & PipedInput/OutputStream for binary data
in java.io.
Regards,
Stéphane
never hands up, never surrender its possible with Executor and SwingWorker
1/ bug for Executor and SwingWorker
2/ hold and check number of thread started by Executor and live SwingWorkers threads with intentions to avoid caught above mentioned bug
3/ check maximum numbers for Executor or restict that to final munber
EDIT changed by OP's requirements
import java.beans.*;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.swing.JDialog;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class ExecutorAndSwingWorker1 {
private static Executor executor = Executors.newCachedThreadPool();
private static void startButton1() {
System.out.println("Starting long Tread == startButton1()");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
private static void startButton2() {
System.out.println("Starting long Tread == startButton2()");
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
}
}
private static void startButton3() {
System.out.println("Starting long Tread == startButton3()");
try {
Thread.sleep(1500);
} catch (InterruptedException ex) {
}
}
private static void startButton4() {
System.out.println("Starting long Tread == startButton4()");
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
}
private static void endButton1() {
System.out.println("Long Tread Ends == startButton1()");
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton3")); // non on EDT
}
private static void endButton2() {
System.out.println("Long Tread Ends == startButton2()");
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton4")); // non on EDT
}
private static void endButton3() {
System.out.println("Long Tread Ends == startButton3()");
}
private static void endButton4() {
System.out.println("Long Tread Ends == startButton3()");
}
private static class MyTask extends SwingWorker<Void, Integer> {
private String str;
private String namePr;
private JDialog dialog = new JDialog();
MyTask(String str) {
this.str = str;
addPropertyChangeListener(new SwingWorkerCompletionWaiter(dialog, str, namePr));
}
#Override
protected Void doInBackground() throws Exception {
if (str.equals("startButton1")) {
startButton1();
} else if (str.equals("startButton2")) {
startButton2();
} else if (str.equals("startButton3")) {
startButton3();
} else if (str.equals("startButton4")) {
startButton4();
}
return null;
}
#Override
protected void process(List<Integer> progress) {
System.out.println(str + " " + progress.get(progress.size() - 1));
}
#Override
protected void done() {
if (str.equals("startButton1")) {
endButton1();
} else if (str.equals("startButton2")) {
endButton2();
} else if (str.equals("startButton3")) {
endButton3();
} else if (str.equals("startButton4")) {
endButton4();
}
}
}
private static class SwingWorkerCompletionWaiter implements PropertyChangeListener {
private JDialog dialog;
private String str;
private String namePr;
SwingWorkerCompletionWaiter(JDialog dialog, String str, String namePr) {
this.dialog = dialog;
this.str = str;
this.namePr = namePr;
}
#Override
public void propertyChange(PropertyChangeEvent event) {
if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) {
System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue());
} else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) {
System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue());
} else {
System.out.println("Thread Status with Name :" + str + ", Something wrong happends ");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton1")); // non on EDT
executor.execute(new ExecutorAndSwingWorker1.MyTask("startButton2")); // non on EDT
}
});
}
private ExecutorAndSwingWorker1() {
}
}
I am not sure this is a solution you should use, and it undermines the simplicity and safety you get from using SwingWorker, but I'll mention it for completeness.
Put two fields where both threads can see them: one boolean, called hasValue, initialized to false, and one int (or long) called countValue. Both must be declared as volatile. When the counter thread is done, put the count in countValue. Then set hasValue to true. The division thread can then check `hasValue' periodically and grab the count when it is available.
If the division is providing values that will be more accurate once it gets the count, this will do. More likely, it is doing some work, then waiting for the count. In this case, set up a third field called countMonitor, defined as final Object. When it finishes the initial work, have it check hasValue. If it's true, grab the value and continue. If it's false, call the wait method on countMonitor and continue when notified. The counter thread, when done, should always call the notifyAll method on countMonitor after putting values in hasValue and countValue.
I've left out a bit here. The javadoc for Object will tell you about needed synchronization and checked exceptions. Your design is straightforward enough that you won't be troubled with the usual supernatural horror stories multi-threading generates. I hope. But you might want to do a bit of research if you go this route. (If you repeat the whole process in the same session, you will definitely want to do a lot of research.)