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
}
Related
I've been working on this stopwatch application for a decent amount of time now but I've encountered some problems.
Problems
The stopwatch isn't starting properly probably due to the clock logic
The stopwatch isn't displaying the numbers onto my Java program properly
It would be nice if anyone were to help explain the flaws in my program and tell me why it isn't working the way I would like it to be. Much help needed and appreciated so here is my code.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Clock {
private static void createWindow() {
// Important
final int windowWidth = 800; // Window width
final int windowHeight = 300; // Window height
// Clock variables
boolean clockRunning = true; // When clock is running, this will be true
int milliseconds = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;
// Create JFrame
JFrame frame = new JFrame(); // JFrame object
// Create timer text
JLabel timer = new JLabel("00:00:00");
timer.setText("00:00:00");
timer.setBounds(355, 100, 100, 40); // Button position
// JButtons
JButton startTimer = new JButton("Start the timer"); // Start timer button
JButton stopTimer = new JButton("Stop the timer"); // Stop timer button
// Event listeners
startTimer.addActionListener(new ActionListener() // Start timer
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("Timer has started");
}
});
stopTimer.addActionListener(new ActionListener() // Stop timer
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("Timer has stoped");
}
});
// Clock logic
if (clockRunning = true) {
milliseconds = 0;
seconds++;
}
if(milliseconds > 1000) {
milliseconds=0;
seconds++;
}
if(seconds > 60) {
milliseconds=0;
seconds=0;
minutes++;
}
if(minutes > 60) {
milliseconds=0;
minutes=0;
hours++;
}
timer.setText(" : " + seconds); // Milliseconds
timer.setText(" : " + milliseconds); // Seconds
timer.setText(" : " + minutes); // Minutes
timer.setText("" + hours); // Hours
// JButton Settings
startTimer.setBounds(10, 100, 200, 30); // Button position
stopTimer.setBounds(570, 100, 200, 30); // Button position
// Frame Settings
frame.setSize(windowWidth, windowHeight); // Window size
frame.setLayout(null); // Frame position
// Add
frame.add(startTimer);
frame.add(stopTimer);
frame.add(timer);
// Frame settings
frame.setVisible(true); // Make frame visible
frame.setResizable(false); // Disables maximize
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Allows the window to be closed
}
public static void main(String[] args) {
createWindow();
}
}
The stopwatch isn't displaying the numbers onto my Java program properly
timer.setText(" : " + seconds); // Milliseconds
timer.setText(" : " + milliseconds); // Seconds
timer.setText(" : " + minutes); // Minutes
timer.setText("" + hours); // Hours
The setText(…) method replaces the existing text.
So the above code is the same as:
timer.setText("" + hours); // Hours
The stopwatch isn't starting properly probably due to the clock logic
For a stop watch you will need to use a Swing Timer so you can update the text at a specified interval.
See: Program freezes during Thread.sleep() and with Timer for the basics of using a Timer.
In my main method of a pomodoro app that is very-much in progress, I have this code:
ActionListener a9 = new ActionListener(){
public void actionPerformed(ActionEvent evt){
DateFormat dateFormat = new SimpleDateFormat("HH:mm");
String currentTime = (String) dateFormat.format(new Date());
combo2.append("You completed " + i + ""
+ " pomodoros! At " + currentTime + " \n");
Toolkit.getDefaultToolkit().beep();
}
};
Timer newTimer = new Timer(500, a9);
newTimer.start();
newTimer.setRepeats(false);
But when I use the "Extract Method" functionality of eclipse, I get this piece outside the main:
private static void generatePomodoro(final JTextArea combo2) {
ActionListener a9 = new ActionListener(){
public void actionPerformed(ActionEvent evt){
DateFormat dateFormat = new SimpleDateFormat("HH:mm");
String currentTime = (String) dateFormat.format(new Date());
combo2.append("You completed " + i + ""
+ " pomodoros! At " + currentTime + " \n");
Toolkit.getDefaultToolkit().beep();
}
};
Timer newTimer = new Timer(500, a9);
newTimer.start();
newTimer.setRepeats(false);
}
This doesn't do what I was hoping for(which is to let me run consecutive countdown timers) . & looks really cryptic to me.. where did the signature come from?
private static void generatePomodoro(final JTextArea combo2)
Thanks
Your main method has signature public static void main(String[] args) and when you try to use Extract Method, Eclipse keeps has to keep new method static thus it would be accessible from main. New function is also private because code prior to refactoring was inaccessible from outside anyway as well as it is a good practice to keep functions private.
I'm wanting to create a stopwatch so to speak in order to score my game. Lets say I have a variable: int sec = 0. When the game starts I want a g.drawString to draw the time to the applet. So for example each second, sec will increment by 1.
How do I go about making it g.drawString(Integer.toString(sec), 40, 400) increment by 1 and draw each second?
Thanks.
EDIT:
I've figured out how to increment it and print it to the screen by using ActionListener and putting g.drawString in there but it prints ontop of each other. If I put g.drawString into the paint method and only increment sec by 1 in the ActionListener there is a a flicker. Should I use Double Buffering? If so how do I go about doing this?
import java.awt.event.*;
import javax.swing.*;
public class StopWatch extends JLabel
implements MouseListener, ActionListener {
private long startTime; // Start time of stopwatch.
// (Time is measured in milliseconds.)
private boolean running; // True when the stopwatch is running.
private Timer timer; // A timer that will generate events
// while the stopwatch is running
public StopWatch() {
// Constructor.
super(" Click to start timer. ", JLabel.CENTER);
addMouseListener(this);
}
public void actionPerformed(ActionEvent evt) {
// This will be called when an event from the
// timer is received. It just sets the stopwatch
// to show the amount of time that it has been running.
// Time is rounded down to the nearest second.
long time = (System.currentTimeMillis() - startTime) / 1000;
setText("Running: " + time + " seconds");
}
public void mousePressed(MouseEvent evt) {
// React when user presses the mouse by
// starting or stopping the stopwatch. Also start
// or stop the timer.
if (running == false) {
// Record the time and start the stopwatch.
running = true;
startTime = evt.getWhen(); // Time when mouse was clicked.
setText("Running: 0 seconds");
if (timer == null) {
timer = new Timer(100,this);
timer.start();
}
else
timer.restart();
}
else {
// Stop the stopwatch. Compute the elapsed time since the
// stopwatch was started and display it.
timer.stop();
running = false;
long endTime = evt.getWhen();
double seconds = (endTime - startTime) / 1000.0;
setText("Time: " + seconds + " sec.");
}
}
public void mouseReleased(MouseEvent evt) { }
public void mouseClicked(MouseEvent evt) { }
public void mouseEntered(MouseEvent evt) { }
public void mouseExited(MouseEvent evt) { }
} // end StopWatchRunner
A small applet to test the component:
/*
A trivial applet that tests the StopWatchRunner component.
The applet just creates and shows a StopWatchRunner.
*/
import java.awt.*;
import javax.swing.*;
public class Test1 extends JApplet {
public void init() {
StopWatch watch = new StopWatch();
watch.setFont( new Font("SansSerif", Font.BOLD, 24) );
watch.setBackground(Color.white);
watch.setForeground( new Color(180,0,0) );
watch.setOpaque(true);
getContentPane().add(watch, BorderLayout.CENTER);
}
}
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();
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;
}