why does it always give the same time? - java

I used the following program to get the clock.What it turned out to be is a static clock ? Why is it so ?
import java.util.*;
import java.awt.*;
import javax.swing.*;
class tester {
JFrame fr = new JFrame();
JPanel p = new JPanel();
JLabel l = new JLabel();
Date d = new Date();
GregorianCalendar gc = new GregorianCalendar();
tester() {
p.setBackground(Color.red);
l.setVisible(true);
p.add(l);
fr.add(p);
fr.setSize(200,200);
fr.setVisible(true);
startClockThread();
}
public void startClockThread() {
Runnable r = new Runnable() {
#Override
public void run() {
startClock();
}
};
new Thread(r).start();
}
public void startClock() {
l.setVisible(true);
while(true) {
l.setText(gc.get(gc.HOUR) + ":" + gc.get(gc.MINUTE) + ":" + gc.get(gc.SECOND));
System.out.println(gc.get(gc.SECOND));
}
}
public static void main(String args[]) {
new tester();
}
}

GregorianCalendar() Constructs a default GregorianCalendar using the current time in the default time zone with the default locale. Java Doc
You can do this way.
while(true) {
GregorianCalendar gc = new GregorianCalendar();
l.setText(gc.get(gc.HOUR) + ":" + gc.get(gc.MINUTE) + ":" + gc.get(gc.SECOND));
}
Now you should understand why you are getting a static clock !

You only create the GregorianCalendar once, and it never gets updated. So the date is always the same.

there's are big problems apart from the one you have spotted:
dont let threads run wild, they'll freeze the ui eventually
each and every access to a Swing component must happen on the EDT
You can solve both easiest by using a javax.swing.Timer
ActionListener nextSecond = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// get time ...
timeLabel.setText(...);
}
}
new Timer(1000, nextSecond).start();

Related

JLabel Overlapping Text in GUI

I'm trying to make a clock using as few resources as possible and just relying on my (limited) knowledge of Java. I've come to a road block however. The clock I wrote works, except rather than the text in the jlabel being replaced, it overlaps itself. I've tried fixing this by clearing the value of timeStamp, but it doesn't seem to be working.
public class Clock extends JFrame{
public static void main (String args[]) {
Clock gui = new Clock();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(50,50);
gui.setVisible(true);
gui.setTitle("Clock");
int a = 1;
while (a == 1){
String timeStamp = new SimpleDateFormat("hh:mm:ss a").format(Calendar.getInstance().getTime());
JLabel label;
label = new JLabel();
label.setText(String.valueOf(timeStamp));
timeStamp = "";
gui.add(label);
label.revalidate();
}
}
}
You should not be creating a new JLabel every iteration.
JLabel label = new JLabel();
gui.add(label);
while (a == 1){
String timeStamp = new SimpleDateFormat("hh:mm:ss a").format(Calendar.getInstance().getTime());
label.setText(String.valueOf(timeStamp));
timeStamp = "";
label.revalidate();
}
You should use a SwingWorker to update the clock. Currently you're doing it on the event dispatch thread and thus interfere with the UI rendering.
Besides that you should reuse the label instead of creating a new one for each timestamp. Currently you're stacking labels on top of each other since gui.add() will just add the new label and won't remove the old ones.
Why are you creating a new JLabel in every iteration of the loop?
Don't do that.
Just create a single label in Clock's constructor.
Also, changing the label's text should be done on the event thread, not the main thread.
While the code you wrote "works", you're missing some things to make a stable Swing GUI.
You must always start a Swing application using the SwingUtilities invokelater method. This puts the creation and the execution of the Swing components on the Event Dispatch thread (EDT).
I separated the creation of the GUI from the execution of the GUI. Separation of concerns makes coding each part easier.
In the Timer Runnable, I again use the SwingUtilities invokeLater method to make sure that the updating of the JTextField with the time happens on the EDT.
I stop the Thread before I exit. Generally, you should stop any threads you start, and not rely on the JVM to clean up for you.
Here's the clock.
And here's the code.
package com.ggl.testing;
import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class SimpleClock implements Runnable {
private JFrame frame;
private JPanel panel;
private JTextField clockDisplay;
private Timer timer;
#Override
public void run() {
frame = new JFrame("Clock");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 6));
clockDisplay = new JTextField(12);
clockDisplay.setEditable(false);
clockDisplay.setHorizontalAlignment(JTextField.CENTER);
panel.add(clockDisplay);
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
timer = new Timer(this);
new Thread(timer).start();
}
public void exitProcedure() {
timer.setRunning(false);
frame.dispose();
System.exit(0);
}
public void setText(String text) {
clockDisplay.setText(text);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Clock());
}
public class Timer implements Runnable {
private volatile boolean running;
private SimpleClock clock;
private SimpleDateFormat timeFormat;
public Timer(SimpleClock clock) {
this.clock = clock;
this.running = true;
this.timeFormat = new SimpleDateFormat("h:mm:ss a");
}
#Override
public void run() {
while (running) {
displayTime();
sleep();
}
}
public void displayTime() {
final Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
final String s = timeFormat.format(date);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
clock.setText(s);
}
});
}
public void sleep() {
try {
Thread.sleep(200L);
} catch (InterruptedException e) {
}
}
public synchronized void setRunning(boolean running) {
this.running = running;
}
}
}

Two example clock window via multithreading/

I am trying to build a simple GUI clock with multithreading.My purpose is making two identical exampl clock window.
public class JavaApplication9 {
public static void main(String[] args) {
JFrame clock = new TextClockWindow();
clock.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
clock.setVisible(true);
}//end main}
class TextClockWindow extends JFrame {
private JTextField timeField; // set by timer listener
private JButton listener;
public TextClockWindow() {
// GUI
timeField = new JTextField(6);
timeField.setFont(new Font("sansserif", Font.PLAIN, 48));
JButton button1 = new JButton("Action");
add(button1);
button1.addActionListener((ActionListener) listener);
ActionListener listener=new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){setBackground(Color.red );
}
};
Container content = this.getContentPane();
content.setLayout(new FlowLayout());
content.add(timeField);
this.setTitle("My_simple_clock"); this.pack();
// Create a 1-second timer and action listener for it.
// Specify package because there are two Timer classes
javax.swing.Timer t = new javax.swing.Timer(1000,
new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Calendar now = Calendar.getInstance();
int h = now.get(Calendar.HOUR_OF_DAY);
int m = now.get(Calendar.MINUTE);
int s = now.get(Calendar.SECOND);
timeField.setText("" + h + ":" + m + ":" + s);
}
});
t.start();
}
This is code without multithreading.But wheni trying to use Runnable some error occured.
In method main Non Static variable cannot be referenced in a static context.
My code with multithreading:
public class MyClock{
public static void main(String[] args) {
Runnable r=new Clocks();
Thread n=new Thread(r);
n.start();
}
public class Clocks implements Runnable {
public Clocks() {}
public void run() {JFrame clock = new TextClockWindow();
clock.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
clock.setVisible(true);
}
please help find the reason why it is not work.runnable is writing correctly....
Is there a reason why you declared Clocks class as inner class ?
Move your Clocks class outside MyClock class and remove the public qualifier if you're declaring the class in the same file. It will start working.

Inefficient Java program when using date

My program seem to be using 20% of the CPU and around 1GB of RAM. I think its because I am looping the date. I am trying to make a clock appear on my JFrame (hours, mins and seconds always updating). My question is, how can I make my program less hungry for power?
Here's my code:
while(true){
Date date = new Date();
time.setText(date.getHours() + " hours " + date.getMinutes()
+ " minutes " + date.getSeconds() + " seconds!");
}
How can I make my program less hungry for power? Make your thread sleep for a while. I assumed the code #Cj1m given is run in a newly started thread.
See java.lang.Thread.sleep(long)
while(true){
SwingUtilities.invokeLater(new Runnable(){ // make sure to run in EDT
#Override
public void run(){
Date date = new Date();
time.setText(date.getHours() + " hours " + date.getMinutes()
+ " minutes " + date.getSeconds() + " seconds!");
}
});
try {
Thread.sleep(1000); // Sleep for 1000 milliseconds.
// Give a shorter interval if you like.
} catch(InterruptedException e) { // Who interrupted my dream?
e.printStackTrace();
}
}
Or use Swing Timer as others described.
Avoid this, use SwingTimer, swing timer not need any loop.
Here a full example:
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class DateAndTimer extends JFrame {
private javax.swing.Timer timer;
private JLabel label ;
private Date ;
public DateAndTimer(){
this.timer = new javax.swing.Timer(1000,getActionTimer());
date = new Date();
label = new JLabel();
add(label,BorderLayout.PAGE_START);
timer.start();
setDefaultCloseOperation(3);
setVisible(true);
pack();
}
public ActionListener getActionTimer(){
ActionListener action = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
label.setText(date.getHours() + " hours " + date.getMinutes()
+ " minutes " + date.getSeconds() + " seconds!");
}
};
return action;
}
public static void main(String...args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
new DateAndTimer();
}
});
}
}
Don't loop. Whatever the application, the above infinite loop will place a constant demand on resources.
In this case, it appears you are using Swing. This is even worse for Swing applications. Infinite loops prevent UI updates.
Use a Swing Timer instead and set an period interval large enough that will allow updates to be observed and will demand less overhead from the CPU. 1000 milliseconds should do.
public class TimerDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Timer Demo");
final JLabel timeLabel =
new JLabel("-----------------------------------------------");
Timer timer = new Timer(1000, new ActionListener() {
SimpleDateFormat format = new SimpleDateFormat("HH' hours 'mm' minutes 'ss' seconds'");
#Override
public void actionPerformed(ActionEvent e) {
Date date = new Date();
timeLabel.setText(format.format(date));
}
});
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(timeLabel);
frame.setVisible(true);
frame.pack();
timer.start();
}
});
}
}
Infinite loop with tiny load (setting date) would obviously take huge CPU, introducing sleep will lessen CPU usage:
while(true){
Date date = new Date();
time.setText(date.getHours() + " hours " + date.getMinutes()
+ " minutes " + date.getSeconds() + " seconds!");
Thread.sleep(1000);//1second update of clock
}

Creating digital clock using a thread

I am trying to create a digital clock using a Thread as this seems to me the logical way one would do it.
I am not sure if I am going about it the right way but what I had in mind is to create the initial current System time using the JFrame constructor and display it as text using a label. In the constructor I then create the thread object with which to update the time.
Struggling a bit and was hoping for some advice as to how to do it right.
setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
setBounds(50, 50, 200, 200);
JPanel pane = new JPanel();
label = new JLabel();
//Font localTime = new Font("Lumina", Font.BOLD , 24);
pane.add(label);
add(pane);
sdf = new SimpleDateFormat("HH:mm:ss");
date = new Date();
s = sdf.format(date);
label.setText(s);
setVisible(true);
runner = new Thread(this);
while(runner == null)
{
runner = new Thread(this);
runner.start();
}
This is then my run() method to update the clock every second.
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
sdf = new SimpleDateFormat("HH:mm:ss");
date = new Date();
s = sdf.format(date);
label.setText(s);
}
catch(Exception e){}
}
Main method.
public static void main(String[] args)
{
new DigitalClock().setVisible(true);
}
The label state should be updated in the Event Dispatch Thread.
You need to add the following modification:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText(s);
}
});
instead of simply updating the label from the separate thread.
It's worth to have a look at the simple description of The Swing GUI Freezing Problem and it's simple solution.
What do you want to improve? It looks ok, while(runner == null) not necessary, you're initialising runner just above.
Check this class http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
scheduleAtFixedRate(TimerTask task, long delay, long period) is probably what you need.

how to put a timer on a JLabel to update itself every second

I created a game and in my swing GUI interface I want to put a timer. The way I do this at the moment is have a field with the current time , gotten with System.currentTimeMillis() which gets it's value when the game starts .In the method of my game i put the System.currentTimeMillis()- field; and it tells you the current time passed since the game started.
Nevertheless, how do get this to update itself every second lets say, so the JLabel will have : timePassed: 0s , timePassed: 1s and so on. Have in mind that i don't use threads in my game at any point.
EDIT: thank you all for your kind suggestions. I used a combination of your answers please give me some feedback.
I have the JLabel as a field called time. (else i cant handle it).
time = new JLabel("Time Passed: " + timePassed() + " sec");
panel_4.add(time);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
time.setText("Time Passed: " + timePassed() + " sec");
}
};
Timer timer = new Timer(1000, actionListener);
timer.start();
Have a look at the swing timer class. It allows to setup recurring tasks quite easily.
This is how I would set my JLabel to update with time & date.
Timer SimpleTimer = new Timer(1000, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
jLabel1.setText(SimpleDay.format(new Date()));
jLabel2.setText(SimpleDate.format(new Date()));
jLabel3.setText(SimpleTime.format(new Date()));
}
});
SimpleTimer.start();
This is then added to your main class and the jlabel1/2/3 get updated with the timer.
new Thread(new Runnable
{
public void run()
{
long start = System.currentTimeMillis();
while (true)
{
long time = System.currentTimeMillis() - start;
int seconds = time / 1000;
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
label.setText("Time Passed: " + seconds);
}
});
try { Thread.sleep(100); } catch(Exception e) {}
}
}
}).start();
wirite this in Constructor
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
jMenu11.setText(CurrentTime());
}
};
Timer t = new Timer(1000, taskPerformer);
t.start();
And this Write out Constructor
public String CurrentTime(){
Calendar cal = new GregorianCalendar();
int second = cal.get(Calendar.SECOND);
int min = cal.get(Calendar.MINUTE);
int hour = cal.get(Calendar.HOUR);
String s=(checkTime(hour)+":"+checkTime(min)+":"+checkTime(second));
jMenu11.setText(s);
return s;
}
public String checkTime(int t){
String time1;
if (t < 10){
time1 = ("0"+t);
}
else{
time1 = (""+t);
}
return time1;
}

Categories