Java Sleep not working in loop [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What I want to do in my java program is, that when I press the button it displays text in textfield in intervals of time.
i.e I press the button then a jFrame pops up and there is a label which shows text like:
1st second:"1st"
then a time lag of say 1 sec
then 2nd thing: "2nd"
I am a newbie and I tried to Google this problem but I couldn't find a solution even after 3-4 hours
I tried a lot of things: sleep, try n catch...
Please write the answer very simplified.
Here is my code:
In the following code, when the button is pressed, the jFrame comes but has a white screen in it and when the sum ends, its screen turns grey and it shows the answer....
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
See.setVisible(true);//See is the JFrame
t007.setVisible(true);//Label in See
l2.setVisible(true);//TextField in See
int ran, g, d, col, ran2;
double y = 1000 * (Double.parseDouble(t2.getText()));
int x = (int) y;
d = 0;
double c = Math.pow(10, Integer.parseInt(t1.getText()));
col = Integer.parseInt(t3.getText());
for (g = 0; g < col;) {
ran = (int) (Math.random() * (c)); // Random Number Creation Starts
if (ran > (c / 10)) {
g = g + 1;
ran2 = ((int) (Math.random() * 10)) % 2;
if (ran2 == 1) {
ran = ran * (-1);
}
d = d + ran;
if (d < 0) {
ran = ran * (-1);
d = d + (2 * ran);
}
l2.setVisible(true);
t007.setText("" + ran);
System.out.println("" + ran);
jButton6.doClick();
//Pausing (Sleep)
try {
Thread.sleep(x);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
l2.setText("" + d);
}

Swing is a single threaded framework, that is, all interactions and modifications to the UI are expected to occur within the context of the Event Dispatching Thread.
The EDT is responsible for, amongst other things, processing repaint requests.
Anything that stops the EDT from running (like Thread.sleep and looping for a long time) will prevent it from processing the events, virtually "hanging" your application until it becomes unblocked...
Now, I tried to decipher what you program was trying to do...but failed, so instead...I made a pretty counter...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TickOver {
public static void main(String[] args) {
new TickOver();
}
public TickOver() {
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 JTextField field;
private JButton button;
private int tick;
private Timer timer;
public TestPane() {
field = new JTextField(10);
field.setEditable(false);
button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
tick = 0;
timer.start();
}
});
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field.setText(Integer.toString(++tick));
if (tick > 4) {
timer.stop();
button.setEnabled(true);
}
}
});
timer.setInitialDelay(0);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(field, gbc);
add(button, gbc);
}
}
}
Take a close look at Concurrency in Swing for more details...

You should never sleep in UI thread, as it make the UI lag. As if the process takes time to complete the UI will get stuck and user experience will get hurt.
Use other mechanisms such as a Timer or SwingWorker
Concurrency in Swing

It's very bad practice to sleep the user interface thread. (As this will cause the application to become unresponsive.) You ought to put all this code inside the Run() method of a Runnable instance:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Your code here.
}
});

The problem is that you run your long running loop on the event dispatch thread. But this is the thread that must dispatch all events of the application like mouse or keyboard events but also repaint events that causes your user interface to get repainted every time it gets 'dirty'. That means, while your for-loop is running, the user interface is not repainted nor are any other events processed. Your UI freezes!
Your jButton5ActionPerformed method should return as soon as possible so that the event dispatch thread can process other events. Your long running operation should be run by a separate thread in the background.
A good starting point is the following tutorial about concurrency in Swing:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
Maybe you can use the SwingWorker class to perform your background work:
http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

Related

A loop in action performed method Doesn't Working in java [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
Question: Write JFrame that when you press the "start" button draws, and keep drawing random colored and sized filled ovals until the "stop" button is pressed.
Problem: loop inside the actionPerformed method() Doesn't Work.
The Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class p6 extends JFrame implements ActionListener
{
String str;
JButton start,stop;
int h=0,w=0;
p6()
{
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1500,1000);
start= new JButton("Start");
stop= new JButton("Stop");
setLayout(null);
start.setBounds(500, 50, 100,30);
stop.setBounds(610, 50, 100,30);
add(start);
add(stop);
start.addActionListener(this);
stop.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
String c=ae.getActionCommand();
if(c=="Start")
{
while(c!="Stop")
{
h+=20;
w+=20;
}
repaint();
}
str=" "+h+" "+w;
}
public void paint(Graphics g)
{
super.paintComponents(g);
g.drawString(str, 100, 100);
//g.drawOval(100, 100, 100, 100);
g.drawOval((int)Math.random()*2000,(int) Math.random()*2000, w,h);
}
public static void main(String[] args)
{
new p6();
}
}
Let's start with How do I compare strings in Java?. This is pretty basic Java 101 and something you REALLY need to understand.
The move onto Concurrency in Swing. Swing is a single threaded. This means that any long running or blocking operations executed within the context of the Event Dispatching Thread will cause the app to "hang" and prevent any further possible updates or interaction.
Swing is also not thread safe, which means that you should only ever update the UI or state the UI depends on, from within the context of the Event Dispatching Thread.
This might seem like a dilemma, but Swing also provides a useful tool to help work with these constraints, see How to user Swing Timer for more details.
Swing also has a well defined and documented painting process, see Painting in AWT and Swing and Performing Custom Painting to get a better understand of how painting works in Swing and how you're suppose to work with it
It is generally recommended not to override the paint method of top level containers (like JFrame). These tend to be composite components and trying to paint on them tends to end up not working very well.
Image from How to Use Root Panes
And you really should make the time to learn how to use layout managers, see Laying Out Components Within a Container. They will save many hours of frustration. The following examples makes use of both a BorderLayout and CardLayout.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
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 {
private CardLayout cardLayout;
private JPanel showPane;
private DrawingPane drawingPane;
public TestPane() {
setLayout(new BorderLayout());
cardLayout = new CardLayout();
showPane = new JPanel(cardLayout);
showPane.add(new EmptyPane(), "Empty");
drawingPane = new DrawingPane();
showPane.add(drawingPane, "Drawing");
cardLayout.show(showPane, "Empty");
add(showPane);
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
stopButton.setEnabled(false);
JPanel actionsPane = new JPanel();
actionsPane.add(startButton);
actionsPane.add(stopButton);
add(actionsPane, BorderLayout.SOUTH);
startButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(false);
stopButton.setEnabled(true);
drawingPane.start();
cardLayout.show(showPane, "Drawing");
}
});
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(true);
stopButton.setEnabled(false);
drawingPane.stop();
cardLayout.show(showPane, "Empty");
}
});
}
}
public class EmptyPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class DrawingPane extends JPanel {
private int h = 0, w = 0;
private Timer timer;
private Random rnd = new Random();
public DrawingPane() {
}
public void start() {
if (timer == null) {
timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
h += 20;
w += 20;
repaint();
}
});
}
timer.start();
}
public void stop() {
if (timer != null) {
timer.stop();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
int x = 0;
int y = 0;
if (w < getWidth() && h < getHeight()) {
x = rnd.nextInt(0, getWidth() - w);
y = rnd.nextInt(0, getHeight() - w);
}
g2d.drawOval(x, y, w, h);
g2d.dispose();
}
}
}
Why make use of CardLayout?
Based on the original code, when not painting, nothing is shown. So I made use of a CardLayout to switch to an "empty" state. Now, it wouldn't be very hard to derive a model to hold the state information and share that between the "empty" and "running" states and show something different on the "empty" state. Equally, we could make use of the glassPane, but I think we're drifting of course.
The purpose is to demonstrate ONE possible solution for showing different states.
Why use two different panes?
First, we don't "need" EmptyPane, we could get away with just an instance of JPanel, but, if you wanted to display something else when not drawing, this is one approach you could take.
The original code had a if statement which means that when not drawing, nothing is painted, so why waste the time and instead just show a "empty" pane instead.
Again, this is just a demonstration of one possible solution.
You have to add these lines before actionPerformed method,
start.setActionCommand("start");
stop.setActionCommand("stop");

How do I display all digits in the animation? [duplicate]

I am trying to create a seven segment display that automatically moves using the timer with the use of the ActionListener and actionPerformed.
I thought that if I use the for, if statement it would automatically loop from 0 to 2 and set the Background color for each segment of the numbers. However, when I display it, it is stuck on just displaying zero and will not count up from there.
Can anyone help me on what I am doing wrong, that makes this stuck on zero?
Here is the programming I have now using JFrame.
import javax.swing.Timer;
public class SevenSegment extends JFrame {
Timer timer = new Timer(100, null);
public SevenSegment() {
timer.start();
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 3; i++) {
if(i == 0) {
lblNumberOne.setBackground(Color.red);
lblNumberTwo.setBackground(Color.red);
lblNumberThree.setBackground(Color.red);
lblNumberFour.setBackground(Color.red);
lblNumberFive.setBackground(Color.red);
lblNumberSix.setBackground(Color.red);
}
else if(i == 1) {
lblNumberTwo.setBackground(Color.red);
lblNumberThree.setBackground(Color.red);
}
else if(i == 2) {
lblNumberOne.setBackground(Color.red);
lblNumberTwo.setBackground(Color.red);
}
}
}
});
}
}
Here's about as simple a Swing GUI clock as you can make.
I did this so I could show you a general way to start all of your Swing GUIs. Oracle has a helpful tutorial, Creating a GUI With JFC/Swing, that will show you how to create all kinds of Swing GUIs.
We start all Swing GUIs with a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
We always create a JPanel to put our Swing components on. The only Swing component that we add to a JFrame is a JPanel or a JScrollPane. This allows us to separate the creation of a JFrame from the rest of the view. The JFrame code is nearly identical for all Swing applications. The only difference is the JPanels you add to the JFrame.
The JFrame code must be called in a specific order. This is the order I use for my Swing applications.
The JPanel code is in a separate paragraph for general tidiness. I like to keep things separate so I can focus on one small part of the GUI at a time.
The updateClockLabel method exists because I need to execute the code one time when I'm creating the JPanel, and five times a second thereafter, to actually update the JLabel.
By the way, I didn't write all this code (all 64 lines) in one shot. I wrote a little, tested a lot. My code was not correct the first time I wrote it, and I don't just mean making typos.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SimpleClock implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new SimpleClock());
}
private JLabel clockLabel;
#Override
public void run() {
JFrame frame = new JFrame("Clock");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
Timer timer = new Timer(200, new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
updateClockLabel();
}
});
timer.start();
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 45, 5, 45));
clockLabel = new JLabel(" ");
clockLabel.setFont(panel.getFont().deriveFont(Font.BOLD, 72f));
updateClockLabel();
panel.add(clockLabel);
return panel;
}
public void updateClockLabel() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H:mm:ss a");
String timeDisplay = LocalTime.now().format(formatter);
clockLabel.setText(timeDisplay);
}
}

Delay between lines in Java [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm creating a card game in Java and would like to portray the appearance of dealing. I have JLabels created and am making them visible by using .setVisible(true) and would like to put a delay between each card being visible.
I've tried using wait() and Thread.sleep() but neither worked. wait() gave me errors and Thread.sleep just paused the entire program, not just each appearance. (This code runs when a "Next" button is pressed so it is in the actionPerformed method)
Note: I am a beginner.. please keep it simple :)
else if(eventName.equals("Next"))
{
rules.setVisible(false);
next.setVisible(false);
inst.setVisible(false);
cardDeck.setVisible(true);
discard.setVisible(true);
tot.setVisible(true);
specialCards.setVisible(true);
// delay here
userCard1.setVisible(true);
// delay here
compCard1.setVisible(true);
// delay here
userCard2.setVisible(true);
// delay here
compCard2.setVisible(true);
// delay here
userCard3.setVisible(true);
// delay here
compCard3.setVisible(true);
}
Use Timers to have the labels being shown after some time.
You will see in the docs that using them is really straight forward.
You could also just insert code that pauses your app for a certain amount of time like Thread.sleep, but this would render your app entirely unresponsive as long as the app waits.
Simple example:
package testTimer;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TimerTest extends JFrame {
// These labels will be shown after some delay
JLabel l1 = null;
JLabel l2 = null;
public TimerTest() {
Container cpane = getContentPane();
cpane.setLayout(new BoxLayout(cpane, BoxLayout.Y_AXIS));
JLabel l = new JLabel("Timer Test");
l.setAlignmentX(Component.CENTER_ALIGNMENT);
cpane.add(l);
l.setVisible(true);
l1 = new JLabel("1");
l2 = new JLabel("2");
cpane.add(l1);
l1.setVisible(false);
cpane.add(l2);
l2.setVisible(false);
// Now prepare two timers, one for each label
int delayForL1Millis = 1000;
Timer t1 = new Timer(delayForL1Millis, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
l1.setVisible(true);
}
});
t1.setRepeats(false);
int delayForL2Millis = 2000;
Timer t2 = new Timer(delayForL2Millis, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
l2.setVisible(true);
};
});
t2.setRepeats(false);
// And start them
t1.start();
t1 = null;
t2.start();
t2 = null;
}
public static void main(String[] argv) {
TimerTest timertest = new TimerTest();
timertest.setVisible(true);
}
}

Any way to delay actions in a Java GUI [duplicate]

This question already has answers here:
How could I add a simple delay in a Java Swing application?
(3 answers)
Closed 6 years ago.
i'm making a poker game for a uni assignment and i was wondering if there is any way to have a method that does as follows ( Note: very roughly written up code )
JTextArea textArea = new JTextArea();
public void printer(String s){
//I want to delay here, for 2 seconds each time i print to the jtextarea
textArea.append(s);
}
public void runGame(){
printer("Dealing cards...");
//I want to delay to add to an effect of the time it takes to actually deal the cards
pokerHand.setVisibility(true);
printer("What you like to do?");
//
//Code here containing running the game
//
printer("Daniel Negreanu folds");
//I want to have a delay here for the time it takes to make a decision.
printer("Phil Hellmuth folds");
Theres many many more instances i want to use this throughout my program, and just wondered if there is any way to do this.
Thanks in advance
EDIT: Not looking to use Thread.sleep() as it doesn't work well with gui.
EDIT2: I want the pokerHand.setVisibility(true), and other methods in my code to execute AFTER the delay, ( using a timer doesn't do this ).
Not looking to use Thread.sleep() as it doesn't work well with gui.
Good, use a Swing Timer instead
I want the pokerHand.setVisibility(true), and other methods in my code to execute AFTER the delay, ( using a timer doesn't do this ).
Yes it does, you're just not using it properly, but since you've not provided any actual code, I can't say "how" you're not using it properly, only from the sounds of it, you are.
Start by taking a look at How to use Swing Timers for more details
The following is very simple example, it uses a Timer to calculate and print the amount of time between the time you clicked the button.
The example updates the UI AFTER the Timer is started, but until the Timer completes, the calculation and result are not generated
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
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 JTextArea ta;
private JButton btn;
private Timer timer;
private LocalTime startTime, endTime;
public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
btn = new JButton("Click");
add(btn, BorderLayout.SOUTH);
timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
endTime = LocalTime.now();
Duration duration = Duration.between(startTime, endTime);
ta.append("Ended # " + endTime + "\n");
ta.append("Took " + (duration.toMillis() / 1000) + " seconds\n");
}
});
timer.setRepeats(false);
ta.setEditable(false);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
startTime = LocalTime.now();
btn.setEnabled(false);
ta.append("Start # " + startTime + "\n");
}
});
}
}
}
First, your code seems to be imperative ("ask user what to do", "game loop goes here") instead of event-driven ("when this happens, do that"). Read up on event-driven programming, which is used on all GUIs, sooner rather than later.
In event-driven code, there is no big difference between "user clicks a button" and "timeout expires" - both will cause events that your code can react to. So start by rewriting your code so that, once you press a button, the "next thing" happens. Then change it again so that once a timer expires, the same "next thing" happens.
Assuming that you have the following code:
// an ActionListener for both clicks and timer-expired events
private nextThingListener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
doNextThing();
}
};
// method that does the next thing
public void doNextThing() {
// change the UI in some way
// if using timers, may also start the next timer
}
You can now associate it to a button using:
// create a button and have it do the "next thing" when clicked
JButton jb = new JButton("do next thing");
jb.addActionListener(nextThingListener);
myInterface.add(jb); // <-- display it in the interface somehow
And you can associate it to a timer as:
// launch a timer that will ring the nextThingListener every 2 seconds
new Timer(2000, nextThingListener).start();
If you want to have the timer ring only once, you can use
// launch a timer that will ring the nextThingListener after 2 seconds
Timer t = new Timer(2000, nextThingListener);
t.setRepeats(false);
t.start();

JDialog does not appear

The program mostly works correctly, but does not open any window. It should show a little dialog on the bottom right of the desktop. But to another person however, compiling the same code works without problems.We have the same Java Runtime (1.8_u40). How can I fix this?
I have put the code below:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ProgressDialog {
private JDialog dialogFrame;
private JProgressBar progressBar;
private JLabel headingLabel;
private Uploader callerUploader;
public ProgressDialog() {
dialogFrame = new JDialog();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException ex) {
System.err.println(ex.toString());
}
dialogFrame.setSize(200, 50);
dialogFrame.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.insets = new Insets(5, 5, 5, 5);
headingLabel = new JLabel();
Font f = headingLabel.getFont();
f = new Font(f.getFontName(), Font.BOLD, f.getSize());
headingLabel.setFont(f);
headingLabel.setOpaque(false);
dialogFrame.add(headingLabel, constraints);
dialogFrame.setUndecorated(true);
// Bottone
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 0;
constraints.weighty = 0;
JButton xButton = new JButton("X");
xButton.setMargin(new Insets(1, 4, 1, 4));
xButton.setFocusable(false);
dialogFrame.add(xButton, constraints);
// Progress bar
constraints.gridx = 0;
constraints.gridy = 1;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.gridwidth = 2;
progressBar = new JProgressBar();
progressBar.setMaximum(100);
progressBar.setMinimum(0);
Dimension dim = new Dimension();
dim.width = 130;
dim.height = 20;
progressBar.setMinimumSize(dim);
progressBar.setStringPainted(true);
progressBar.setBorderPainted(true);
dialogFrame.add(progressBar, constraints);
xButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialogFrame.dispose();
stoppedUploaderClose();
}
});
}
private void autoPosition() {
// Per il posizionamento in basso a destra
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
// altezza taskbar
Insets toolHeight = Toolkit.getDefaultToolkit().getScreenInsets(dialogFrame.getGraphicsConfiguration());
dialogFrame.setLocation(scrSize.width - 5 - dialogFrame.getWidth(), scrSize.height - 5 - toolHeight.bottom
- dialogFrame.getHeight());
}
public void destroy() {
new Thread() {
#Override
public void run() {
try {
Thread.sleep(500);
for (float i = 1.00f; i >= 0; i -= 0.01f) {
dialogFrame.setOpacity(i);
Thread.sleep(15);
}
dialogFrame.dispose();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
public void setUploader(Uploader callerUploader) {
this.callerUploader = callerUploader;
}
public void set(int n) {
progressBar.setValue(n);
progressBar.setString(n + "");
}
public void setMessage(String headingLabel) {
this.headingLabel.setText(headingLabel);
autoPosition();
dialogFrame.setShape(new RoundRectangle2D.Double(1, 1, 200, 50, 20, 20));
dialogFrame.setVisible(true);
}
public void setWait() {
headingLabel.setText("Waiting link...");
}
public void close() {
dialogFrame.dispose();
}
public void stoppedUploaderClose() {
try {
callerUploader.stopUpload();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're making Swing calls that change the state of the Swing components of GUI from within a background thread, and this can and will lead to unpredictable errors. Better to use a Swing Timer rather than Thread.sleep(...) since all code within the Timer's ActionListener is called on the Swing event thread.
Also, I have to wonder
Just what the Uploader class does,... Likely it creates long running code, which begs the question, is it being called appropriately within a background thread? This looks like a good spot for a SwingWorker.
How is this dialog code being called?
For more direct help, consider creating and posting an sscce or a minimal example program/mcve where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
Edit: OK, I normally don't do this, but I looked at your code in your GitHub project link, and as I suspected, Uploader does long-running code on the Swing event thread, and makes calls to this class you've posted above. I suggest that you use a SwingWorker for long-running code, that you use its setProgress(...) method to change its progress state from 0 to 100, and that you use a PropertyChangeListener to listen for changes to this state, and then set the JProgressBar's value based on this. It will take a lot of work on your part, but will be well worth it. For the details, look at: Lesson: Concurrency in Swing
I have some example SwingWorker programs that you can find here:
Cant get JProgressBar to update from SwingWorker class
MVC Progress Bar Threading
How do I make my SwingWorker example work properly?
JProgressBar without JButton and PropertyChangeListener
Understanding Java ExecutorService

Categories

Resources