Everytime my counter reaches 4 I want it to play a beep sound and go back to '1' and again count up to 4 play the beep sound and so on.
I probably shouldn't place this in a label, because the counter doesnt run at all!
I don't get any errors but the label says; counter is 4 and doesnt count or anything.
Can you help me make this counter work properly? I also used printline but that
gave some errors too.
My code for the counter is this:
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
label1.setVisible(true);
int counter = 1;
while(counter < 5 )
{
label1.setText("counter is " + counter);
counter = counter + 1 ;
}
counter = 1;
tk.beep();
}
});
Spawn a new thread to count, wait, and update the GUI.
You're doing all of this work in the Event Dispatch Thread, which is the only thread which updates the GUI. So when you set the text of the label, it doesn't get updated on the screen until the method returns and the Event Dispatch Thread handles the repaint operation.
You need to spawn a new thread to do this, rather than just running it in a loop which executes immediately. Just have the actionPerformed method spawn a new Thread which handles this instead. Loop, count, and update in this thread, waiting with Thread.sleep between updates. To update the label text, create a new Runnable that will update the label to the next value and put it on the Event Dispatch Thread with SwingUtilities.invokeLater. Keep this thread running in the background until you need it. I would recommend checking a shutdown status boolean every loop through, and quitting when it's set to false. This way, you can shut down the thread cleanly at any time. Or, if you want it to countdown and beep only once, you can have the thread just end after one iteration of counting.
There are lots of questions on Stack Overflow that detail each of these steps, so I won't repeat this information here.
How does the event dispatch thread work?
How to create the thread which does the counting
After changing the value you need to repaint. Also, I assume you actually want to count the seconds in which case you need to use a Timer to kick off the action of changing the label and possibly playing a sound.
If I understand correctly what you want , the below code should accomplish your goal.
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
label1.setVisible(true);
Runnable runnable = new Runnable() {
int counter =1 ;
public void run() {
while(true) {
while (counter<5) {
SwingUtilties.invokeLater(new Runnable() {
public void run() {
label1.setText("counter is " + counter);
}
});
counter = counter + 1 ;
try {
Thread.sleep(1000);
}catch(InterruptedException ex) {
System.err.println(ex.toString());
}
}
counter = 1;
tk.beep();
}
}
};
new Thread(runnable).start();
});
Maybe this is does what you intened, every 4th button press it resets and beeps
loginButton.addActionListener(new java.awt.event.ActionListener() {
int counter = 1;
public void actionPerformed(ActionEvent arg0) {
label1.setVisible(true);
if (counter < 5) {
label1.setText("counter is " + counter);
label1.repaint();
++counter;
} else {
counter = 1;
tk.beep();
}
}
});
Your loop stops after the first 4 and never called again. since the text is changing to fast, you can only see the last result
int counter = 0;
while (//when do you want it to stop?)
{
// print what you want (using (counter % 4) + 1)
if ((counter % 4) == 0)
{
tk.beep();
}
}
Related
Hi everyone i would like to ask if is it possible not to use timer in Java netbeans to display on my JLabel all value of my variable "counter" using while loop. Here is my sample code.
int counter = 0;
while (counter < 10) {
lblDisplay.setText("Completed " + Integer.toString(counter));
try {
Thread.sleep(1000);
lblDisplay.setText("Completed " + Integer.toString(counter));
} catch (InterruptedException ex) {
Logger.getLogger(Increment.class.getName()).log(Level.SEVERE, null, ex);
}
counter++;
}
in using of system.out.println it was displayed but in my Label was not.
Yes it's possible to avoid using a Swing Timer to achieve this, but if you did this then:
You'd have to make sure that the loop and the Thread.sleep(...) were run in a background thread off of the Swing event thread. If you don't do this, you will freeze the event thread and thus freeze your GUI and render it useless.
And then you'd have to make sure that when you only make Swing calls from the background thread, you take pains to queue those calls onto the Swing event dispatch thread. If you don't do this, you will run the risk of causing occasional very hard to debug threading errors.
Because of the extra work involved and the risk of getting it wrong, you'll find that it is much simpler and safer to just use a Swing Timer. For instance your posted code looks like it's at grave risk of putting the entire GUI/application to sleep since it has both a while loop and a Thread.sleep(...) called without concern for threading.
For example, without a Timer, your code could look something like (caveat: code not compiled nor tested):
new Thread(new Runnable() {
public void run() {
int counter = 0;
while (counter < 10) {
lblDisplay.setText("Completed " + Integer.toString(counter));
try {
Thread.sleep(1000);
final int finalCounter = counter;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
lblDisplay.setText("Completed " + finalCounter);
}
});
} catch (InterruptedException ex) {
Logger.getLogger(Increment.class.getName()).log(Level.SEVERE, null, ex);
}
counter++;
}
}
}).start();
That's a bit more complicated than I like, while the Swing Timer could look like:
int delay = 1000;
new Timer(delay, new ActionListener() {
private int count = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (count < 10) {
lblDisplay.setText("Completed " + counter);
} else {
((Timer) e.getSource()).stop(); // stop the Timer
}
counter++;
}
}).start();
Which is simpler and safer than the previous.
For some reason even though I am using the exact code example from oracle's website for the Swing Timer it is not waiting for 1 second. It just skips to the JOptionPane that says "Your score was etc etc".
Here is my source code for a school project. Why is this not working and not waiting for 1 second before running the rest of the code?
//Check to see if user has enetered anything
if(!answered)
{
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
afk = true;
incorrect += 1;
answered = true; //This breakes it out of the loop
}
A timer is used to run a callback after a specific amount of time. If you simply want to delay, you can either move the code to be run after the delay into the taskPerformer action listener.
Thread.sleep(1000) is not ideal here, because it will cause the UI to completely freeze as you will make the UI thread sleep.
What can do to have a Swing Timer object fire every 2 seconds for ten times and do a different thing in each firing? Using:
// task one
int delay = 2000;
Timer swingTimer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// task two
}
});
swingTimer.start();
only enables me to do two things. But I want to use the timer to execute one chunk of code, wait 2 seconds, execute another chunk of code, wait another 2 seconds, do another thing and so on and so forth for like 10 consecutive tasks. Thanks.
Use some kind of counter in your actionPerformed method to determine which cycle your up to....
private int cycle = 0;
//...
Timer swingTimer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
switch (cycle) {
case 0:
// Task #1
break;
case 1:
// Task #2
break;
case 2:
// Task #3
break;
default:
// All done...
((Timer)e.getSource()).stop();
}
cycle++;
}
});
You could set up a new non-repeating Timer at the conclusion of each actionPerformed, seeding it with the next ActionListener/task to be executed, but this can get messy quickly...
This is basic concept of the idea. You could devise a common interface for each task, add them to a List of some kind and simply use list.remove(0) to pop the next one of the List and execute it. You would continue until the List was empty.
private int cycle;
Timer swingTimer = new Timer(delay, new ActionListener() {
public void actionPerformed(ActionEvent e) {
controller.callMethod(cycle); // controller decides what to do
cycle++;
}
});
And don't forget to stop the timer after it completes a desired number of cycles.
I am working on Deal or No Deal with a user interface. The first problem I ran into was how to wait for a button action to continue, and I used Count Down Latches and it worked perfectly. But whenever, I click a button, everything in my JFrame disappears and comes back when you mouse over, it all of a sudden reappears when I press another buttton (This never happened before I used Count Down Latches, and this also happens with Semaphores, etc.) I'll try to keep my code as relevant as possible.
public CountDownLatch cdl = new CountDownLatch(1);
pickFirst();
try {
cdl.await();
} catch (Exception E) {
}
while (banker.findCasesLeft() > 2) {
banker = new Banker(Main.f.values);
for (i = casesToPick; i >= 1; i--) {
cdl = new CountDownLatch(1);
pickCase();
picked = false;
try {
cdl.await();
} catch (Exception E) {
}
}
^^^ That was my class that deals with picking cases Below is class with actionlisteners
public void actionPerformed(ActionEvent ae) {
if (!Main.me.pickedFirst) {
Main.me.pickedCase = caseNo;
Main.f.log += "You picked to keep case " + caseNo + ".\n";
setText(caseNo + "\np");
Main.f.changeLog();
Main.me.pickedFirst = true;
Main.me.cdl.countDown();
} else {
int value = Main.me.values[caseNo-1];
Main.me.values[caseNo] = 0;
Main.f.values[getIndex(value)].setSelected(true);
Main.f.log += "You picked to get rid of case " + caseNo + ". It contained $" + value + ".\n";
Main.f.changeLog();
Main.me.picked = true;
Main.me.cdl.countDown();
}
setEnabled(false);
}
Note that the await() method of CountDownLatch "Causes the current thread to wait until the latch has counted down to zero." If that thread is the event dispatch thread, GUI updates will be blocked until the wait condition changes. In general, CountDownLatch is meant to allow separate threads to rendezvous; it should't be used to within the event dispatch thread. This complete example, which coordinates multiple SwingWorker instances, may help clarify the usage.
I want my program to start off using a countdown timer that will be displayed to the user. The only way I can think to do that is to label.setText() and Thread.sleep(). I've tried for about 20min trying to get it to work, but can't seem to crack it. Help?
Use a Swing timer. Basically you create a class that implements ActionListener, create a javax.swing.Timer, and the actionPerformed method of the ActionListener gets called at an interval you specify. In your actionPerformed method, check the time, and update the value to be displayed when appropropriate, and call repaint(). Use an interval of 0.1 second, and your countdown will be smooth and accurate enough.
I wouldn't count on the accuracy of Thread.sleep, but:
for(int i = 20; i >= 0; i--) {
label.setText(i + " seconds remaining");
Thread.sleep(1000);
}
This will, of course, block the UI thread while sleeping, so you probably need to run it on a separate thread. This means you will need something like SwingUtilities.InvokeLater to update the UI, since you are using a thread different than the UI one:
for(int i = 20; i >= 0; i--) {
SwingUtilities.InvokeLater(new Runnable() {
public void run() {
label.setText(i + " seconds remaining");
}
});
Thread.sleep(1000);
}