I make a simple application which contain a quiz questions and the user select an answer but i need your help in adding a count down timer in my app for 20 sec when this time is up it will transfer directly to the next question and when the user answer in time it will transfer to next question
Thank you
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class Countdown extends JFrame {
// Countdown 42 seconds
public static int counterValue = 42;
public static Timer timer;
public static JLabel label;
public Countdown() {
initGUI();
}
private void initGUI(){
BorderLayout thisLayout = new BorderLayout();
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.getContentPane().setLayout(thisLayout);
label = new JLabel();
label.setText(String.valueOf(counterValue));
this.getContentPane().add(label, BorderLayout.CENTER);
this.setTitle("Countdown Example");
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
Countdown countdown = new Countdown();
Countdown.timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// =1 sec
Countdown.counterValue--;
Countdown.label.setText(String.valueOf(counterValue));
if(Countdown.counterValue == 0){
System.out.println("Counterdown ausgelaufen!");
// Timer stop
Countdown.timer.stop();
}
}
});
// Timer start
timer.start();
}
}
Taken from http://blog.mynotiz.de/programmieren/java-countdown-und-timer-am-beispiel-von-swing-1707/ ( German )
The "Android way" to do timed things is by posting Runnable tasks to a Handler.
Related
How to move with smooth motion for JPanel and update JLabel at same time?
I want to show current time on a JFrame so I created a new java.util.Timer and update to label every one second.
I created another Java thread to as well, move the panel component.
But while moving the panel and showing (updating) time on the frame, panel refreshing to form original position.
So I search that problem in Google and can't find the solution.
//Code to move jPanel smoothly
Thread t = new Thread(){
int i = 0 ;
public void run(){
while(i<150){
i++;
jPanel2.setLocation(i, jPanel2.getY());
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}
};
t.start();
// Code to show Time
Timer t = new javax.swing.Timer(1, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jLabel1.setText(new Date()+"");
}
});
t.start();
Here is a small example, how to provide animation and update for a component.
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;
/**
* <code>MovedClock</code>.
*/
public class MovedClock {
private final JLabel clock = new JLabel();
private final DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm:ss");
private void startUI() {
JFrame frame = new JFrame("Moved clock");
frame.setLayout(null); // usually it's a bad idea, but for animation we need this.
clock.setBounds(0, 50, 50, 20);
frame.add(clock);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
updateClock();
Timer clockTimer = new Timer(1000, e -> updateClock());
clockTimer.start();
// 15 milliseconds for about 60fps
Timer moveTimer = new Timer(15, new ActionListener() {
private int count = 1;
private int increment = 1;
#Override
public void actionPerformed(ActionEvent e) {
if (count == 435 || count == 0) {
increment = -increment;
}
Point loc = clock.getLocation();
loc.x += increment;
clock.setLocation(loc);
count += increment;
}
});
moveTimer.start();
}
private void updateClock() {
clock.setText(LocalTime.now().format(format));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new MovedClock()::startUI);
}
}
As I corrected my use of some features instead of others, I post this. I try to use JSpinner to choose a Date and Time and put it then into a timer and the trigger must be the Date and Time I choosed.
How could I use it to change the time too by moving the arrows and to put the date and time in the timer ?
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerModel;
import java.util.Calendar;
import java.util.Date;
import javax.swing.Timer;
public class SpinnerDateSample {
public static void main(String args[]) {
JFrame frame = new JFrame("JSpinner Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SpinnerModel model1 = new SpinnerDateModel();
JSpinner spinner1 = new JSpinner(model1);
spinner1.addChangeListener(new CalendarListener());
JLabel label1 = new JLabel("Dates/Date");
JPanel panel1 = new JPanel(new BorderLayout());
panel1.add(label1, BorderLayout.WEST);
panel1.add(spinner1, BorderLayout.CENTER);
frame.add(panel1, BorderLayout.CENTER);
frame.setSize(200, 90);
frame.setVisible(true);
}
}
private class CalendarListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSpinner jSpinner = (JSpinner) e.getSource();
Date date = (Date) jSpinner.getValue();
long delay = date.getTime() - System.currentTimeMillis();
timerStart();
if (delay > 0) {
timer.setInitialDelay((int) delay);
timer.restart();
}
}
}
TimerStart() {
this.timer = new Timer(Integer.MAX_VALUE, (ActionEvent evt) -> {
System.out.println("okey");
});}
TimerTask is a legacy class, rather you can use ScheduledExecutorService for executing a task at scheduled intervals, which is a best practice as shown below:
Selection6Runable class:
public class Selection6Runable implements Runnable {
public void run() {
//Add code for Selection6 Logic,
// this code will be run everytime when the scheduler runs
}
}
Using the above code:
ScheduledExecutorService scheduledService= Executors.newScheduledThreadPool(1);
//Change the below time interval according
//to the data received i.e., CalDcB.getSelectedItem()
scheduledService.scheduleAtFixedRate(()-> new Selection6Runable(),
0, 1000L, TimeUnit.MILLISECONDS);
You can look here for more details
I'm trying to make a countdown timer that only run when the window is on top of my screen.
I tried with this :
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class TimerVisible extends JFrame implements WindowFocusListener{
static TimerVisible frame = new TimerVisible("chrono",2,1,3);//I set a random time
JTextArea display;
private Counter counter;
public static void main(String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addComponentsToPane();
frame.pack();
frame.setVisible(true);
}
private void addComponentsToPane() {
display = new JTextArea();
display.setEditable(true);
JScrollPane scrollPane = new JScrollPane(display);
scrollPane.setPreferredSize(new Dimension(500, 450));
getContentPane().add(scrollPane, BorderLayout.CENTER);
addWindowFocusListener(this);
}
public TimerVisible(String name, int hours, int minutes, int secondes) {
super(name);
counter=new Counter(hours, minutes, secondes); //Counter is in secondes but is created with hours, minutes and seconds
}
public void windowGainedFocus(WindowEvent e) {
displayMessage("WindowFocusListener method called: windowGainFocus.");
try{
while(counter.getCounter()!=0){
Thread.sleep(1000);
displayMessage(counter.toString());
counter.decrement();
}
}
catch(InterruptedException exc){
System.exit(-1);
}
}
public void windowLostFocus(WindowEvent e) {
displayMessage("WindowFocusListener method called: windowLostFocus.");
}
private void displayMessage(String msg) {
display.append(msg+"\n");
System.out.println(msg);
}
}
When I run this program, it display the messages and the countdown on my terminal and not the window, but if I set the while loop under comment, it display correctly the message on the window. Is anybody got an idea why I got this difference?
Thank you
Your while loop is running on the Swing event thread, blocking it and preventing it from painting to the GUI or interacting with the user. Use a Swing Timer instead. Note that with a Swing Timer you won't have a while loop, but instead the actionPerformed will be called repeatedly until you stop the Timer.
Something like this could be close to working (code not tested)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
public class TimerVisible extends JFrame implements WindowFocusListener{
private static final int TIMER_DELAY = 1000;
static TimerVisible frame = new TimerVisible("chrono",2,1,3);//I set a random time
JTextArea display;
private Counter counter;
Timer timer = null;
public static void main(String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addComponentsToPane();
frame.pack();
frame.setVisible(true);
}
private void addComponentsToPane() {
display = new JTextArea();
display.setEditable(true);
JScrollPane scrollPane = new JScrollPane(display);
scrollPane.setPreferredSize(new Dimension(500, 450));
getContentPane().add(scrollPane, BorderLayout.CENTER);
addWindowFocusListener(this);
}
public TimerVisible(String name, int hours, int minutes, int secondes) {
super(name);
counter=new Counter(hours, minutes, secondes); //Counter is in secondes but is created with hours, minutes and seconds
}
public void windowGainedFocus(WindowEvent e) {
displayMessage("WindowFocusListener method called: windowGainFocus.");
if (timer != null && timer.isRunning()) {
return;
}
timer = new Timer(TIMER_DELAY, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (counter.getCounter() <= 0) {
timer.stop();
} else {
displayMessage(counter.toString());
counter.decrement();
}
}
});
timer.start();
}
public void windowLostFocus(WindowEvent e) {
displayMessage("WindowFocusListener method called: windowLostFocus.");
}
private void displayMessage(String msg) {
display.append(msg+"\n");
System.out.println(msg);
}
}
I had to make a sort of animation thing in netbeans gui. So I was studying about swing timer on the internet and from what i found i worte a method which will change images in jLabel after certain time periods.
public void animation() throws InterruptedException {
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
t++;
System.out.printf("Reading SMTP Info. %d\n",t);
if(t%2==1){
jLabel3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/oncsreen_keypad/a.jpg")));
}
else{
jLabel3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/oncsreen_keypad/b.jpg")));
}
}
};
Timer timer = new Timer( 1000 , taskPerformer);
//timer.setRepeats(false);
timer.start();
Thread.sleep(5000);
}
this method is called nowhere. But if the System.out.printf works then changing image in jLabel should also work. But actually in the run those lines are having no effect on the jLabel.
So what should be the right approach.
Dont stop the main thread with Thread.sleep.., use the Swing Timer and give him the delay, when your image should change.
I made a small example for you.
This is the class which generates the JFrame with a JPanel, which contains the JLabel.
package timerdemo;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
*
* #author ottp
* #version 1.0
*/
public class Gui extends JFrame {
private JLabel jLabel;
private Timer timer;
private boolean chromeShown;
public Gui() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800, 600);
JPanel panel = new JPanel(new BorderLayout());
jLabel = new JLabel(new ImageIcon("/home/ottp/Downloads/chrome.png"));
chromeShown = true;
panel.add(jLabel);
timer = new Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(chromeShown) {
jLabel.setIcon(new ImageIcon("/home/ottp/Downloads/ok.png"));
chromeShown = false;
} else {
jLabel.setIcon(new ImageIcon("/home/ottp/Downloads/chrome.png"));
chromeShown = true;
}
}
});
timer.start();
this.getContentPane().add(panel);
this.setVisible(true);
}
}
And start it...
package timerdemo;
import javax.swing.SwingUtilities;
/**
*
* #author ottp
*/
public class TimerDemo {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Gui();
}
});
}
}
After starting the timer in your Gui class, the image on the JLabel will be changed every 5 seconds, condition for this is the boolean flag. You could use your if... else construct also there.
Hope this helps
Patrick
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int count = jSlider1.getValue();
int delay = jSlider2.getValue();
int valueOfSlider = jSlider2.getValue();
int valueOfSlider2 = jSlider1.getValue();
while (count > 0)
{
count--;
String count2 = ""+count;
jLabel3.setText(count2);
try {Thread.sleep(delay); }
catch (InterruptedException ie) { }
}
It will eventually show the final number on the jLabel but it does not incrementally update the number. any help
Swing is single-threaded. Therefore, long-running tasks should never take place in the EDT. This includes sleeping. Instead, use a javax.swing.Timer. This will delay in a background thread, and then post an action to be executed in the EDT.
See also:
How to Use Swing Timers
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public final class JLabelUpdateDemo {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame("Update JLabel Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(JTimerLabel.getInstance());
frame.setSize(new Dimension(275, 75)); // used for demonstration purposes
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer t = new Timer(1000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
int val = Integer.valueOf(JTimerLabel.getInstance().getText());
JTimerLabel.getInstance().setText(String.valueOf(++val));
}
});
t.start();
}
private static final class JTimerLabel extends JLabel{
private static JTimerLabel INSTANCE;
private JTimerLabel(){
super(String.valueOf(0));
setFont(new Font("Courier New", Font.BOLD, 18));
}
public static final JTimerLabel getInstance(){
if(INSTANCE == null){
INSTANCE = new JTimerLabel();
}
return INSTANCE;
}
}
}
This SSCCE imitates a counter that will count up from 0 every second (i.e. update the JLabel instance) until the application is terminated.
Your problem is that your doing something time consuming in an ActionPerformed callback, which executes in the event thread. In callbacks, you should do something quickly and return, even if that "something" is spawning a thread. The GUI can't update while you're occupying the event thread, it will only update after your callback returns.