So I'm starting to get really interested about Threads and how it works, Kinda amazing how it works but I just learned about it today and trying to make a program to work. So im trying to make a clock that gives me in a Jlabel a current clock which is right now and a Textfield where I enter the time by myself. so what I want to do is it should start by showing me the time, when pressing the button "Set time" it should change the time as I entered and go from there as a clock.
So my problem right now is that whenever I press the Set time now it changes for a second and then turn back to the current clock again. and I don't really know how to stop the first thread when pressing Set time (Which starts the second Thread)
However I think this is kinda simple but fun to work with,
EDIT: I Also found out that I will have a problem by counting when entering a own "clock". My code:
public Clock() {
initialize();
Thread1();
}
.......
JButton btnSetTime = new JButton("Set time");
btnSetTime.setBounds(474, 262, 89, 23);
frame.getContentPane().add(btnSetTime);
btnSetTime.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnSetTime) {
Thread2();
}
}
});
}
public void Thread2() {
Thread t2 = new Thread() {
public void run() {
try {
for(;;) {
int hour = Integer.parseInt(tfhour.getText());
int minute = Integer.parseInt(tfminute.getText());
int second = Integer.parseInt(tfsecond.getText());
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};t2.start();
}
public void Thread1() {
Thread t1 = new Thread() {
public void run() {
try {
for(;;) {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};t1.start();
}
}
So as I can see, the int hour = Integer.parseInt(tfhour.getText()); will probably not count as a Clock if I change to my own clock later on if i'm right? In that case, How can I fix it?
I hope I have all my problems out here in the post and I hope anyone here is willing to help me aswell :)
EDIT:
To make it easier to see:
EDIT PART 3:0
You have to define a global variable to stop the thread 1, when the thread 2 starts. Here is an example,
//define a variable that controls the thread 1
static boolean clockSet = false;
Now thread 1 is written such as it runs only when the clockSet is false, that is clock not set by a click.
Thread t1 = new Thread(){
public void run(){
while(!clockSet){
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
In your thread 2, set the clockSet to true, so the thread 1 will stop. I see you are just displaying the value entered, but not setting those on a Calendar object. So create a Calendar object in thread 2, set the user defined values, and increment the time after every second of sleep.
Thread t2 = new Thread(){
public void run(){
clockSet = true;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(tfhour.getText()));
cal.set(Calendar.MINUTE, Integer.parseInt(tfminute.getText()));
cal.set(Calendar.SECOND, Integer.parseInt(tfsecond.getText()));
while(true){
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
try {
sleep(1000);
cal.add(Calendar.SECOND, 1);
} catch (InterruptedException e) {
e.printStackTrace();}
}
}
};
Have fun..!
Sure, you see the code
try {
for(;;) {
int hour = Integer.parseInt(tfhour.getText());//this one
int minute = Integer.parseInt(tfminute.getText());//and this one
int second = Integer.parseInt(tfsecond.getText());//and this too
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
you are setting hour, minute & second each and every time inside the for loop. So the clock is reseting.
Make them to get initialize only once, i.e. take them out of the loop.
Further this code
for(;;) {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
lblKlockan.setText(hour + ":" + minute + ":" + second);
sleep(1000);
}
is making your timer work as clock and not a timer because after 1 sec. the hour, minute & second are set to the values according to the time you get from Calendar.
Due to this your code will work as a clock that show the current time.
In my opinion you don't need the second thread at all. What I would do in this case is create three Int fields, hour-, minute- and second-offset, which you change when the button is pressed to, for example, hourOffset = Calendar.HOUR_OF_DAY - Integer.parseInt(tfhour.getText())%24; (example for the hours). Than you just need to add the offset to the time in thread1, which allways works since you start with 0 as offset.
Related
I have a TimePicker with an interval of 30 minutes. When I open up a custom dialog with this picker it works well and it shows me 2 choices correctly (0, 30) in the minutes spinner. But, when I confirm and I come back to the activity it shows me a wrong result like: 10:01 instead 10:30. That's the method I use to set the interval
public static void setTimePickerInterval(TimePicker timePicker) {
try {
NumberPicker minutePicker = (NumberPicker) timePicker.findViewById(Resources.getSystem().getIdentifier("minute", "id", "android"));
minutePicker.setMinValue(0);
minutePicker.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1);
List<String> displayedValues = new ArrayList<>();
for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
displayedValues.add(String.format("%02d", i));
}
minutePicker.setDisplayedValues(displayedValues.toArray(new String[0]));
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
}
}
TIME_PICKER_INTERVAL is set as 30. And that's what i wrote in the activity inside the method that open a custom dialog with the picker
// Get time picker object.
TimePicker timePicker = customView.findViewById(R.id.timePickerExample);
Utils.setTimePickerInterval(timePicker);
timePicker.setIs24HourView(true);
timePicker.setHour(hour);
timePicker.setMinute(minute);
dpStartDate.init(year, month, day, new DatePicker.OnDateChangedListener() {
#Override
public void onDateChanged(DatePicker datePicker, int year, int month, int day) {
MainActivity.this.year = year;
MainActivity.this.month = month;
MainActivity.this.day = day;
}
});
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker timePicker, int hour, int minute) {
Log.i(TAG, "onTimeChanged: " + minute +" "+ hour);
MainActivity.this.hour = hour;
MainActivity.this.minute = minute;
}
});
Log.i(TAG, "onTimeChanged: " + minute +" "+ hour); shows what I'm setting. The hours are corrected, minutes not. It seems that instead shows "0, 30" it shows and select "0, 1". Any idea?
I'm trying to create a clock programm with customizable options but since I'm a beginner I'm running into some problems. I tried using the DigitalClock project but there's too many things in it for me right now
I looked into Timer and ScheduledExecuterService but I don't know how to use and where to place them.
I also tried to set a color to the background but the error was that it could be over ran.
How can I repeat the process in milliseconds, add a background and make the code lighter ?
public Clock() {
initComponents();
Calendar cal = new GregorianCalendar();
int second = cal.get(Calendar.SECOND);
int minute = cal.get(Calendar.MINUTE);
int hour = cal.get(Calendar.HOUR_OF_DAY);
/////////////////////////////////////////////////////////////
if (second < 10){
time.setText(" "+hour+": "+minute+":0"+second+"");
}
else if (minute < 10){
time.setText(" "+hour+":0"+minute+": "+second+"");
}
else if (hour < 10){
time.setText("0"+hour+": "+minute+": "+second+"");
}
else if (hour < 10 & minute < 10){
time.setText("0"+hour+":0 "+minute+": "+second+"");
}
else if (minute < 10 & second < 10){
time.setText(" "+hour+":0"+minute+":0"+second+"");
}
else if (hour < 10 & minute < 10 & second < 10){
time.setText("0"+hour+":0"+minute+":0"+second+"");
}
else {
time.setText(hour + " : " + minute + " : " + second+"");
}
////////////////////////////////////////////////////////////////
}
If you want to make it simple then you can simple do the following:
public static void main (String[] args) throws Exception
{
final SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss:SSS");
while(true) {
System.out.println(sf.format(new Date()));
Thread.sleep(1);
}
}
But this might miss a millisecond entry in between. For example, it might go directly to 310 after 308 and miss 309 in between. But since we are talking about 1/1000th of a second, in real life it is very unlikely to be noticed.
Your code will reduce to something like following:
public Clock() {
public static void main (String[] args) throws Exception {
initComponents();
final SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss:SSS");
while(true) {
time.setText = sf.format(new Date());
Thread.sleep(1);
}
}
}
final SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss:SSS");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println(sf.format(new Date()));
}
}, 0 , 1000000);
Will repeat in 1 ms.
So I have made a program where I made so a clock appears when running the program. so. When I press a button "Start" a clock should go random inside a bounds and go as a clock aswell (I mean like digital, 15:18:19, 15:18:20). but my problem is now whenever I press the program. the clock stays on the same spot and when changing the sleep time to etc. 500. then it starts to move but the time semms to go alot faster (since it should sleep 1000). however I don't see the problem in the code where it should go. but however maybe some of you could help me with that.
public void startClock() {
Thread t2 = new Thread() {
public void run() {
if (clocking) {
Random rand = new Random();
while(clocking){
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
movingClock.setText(hour + ":" + minute + ":" + second);
int x = rand.nextInt(100) + 1;
int y = rand.nextInt(100) + 1;
movingClock.setBounds(x, y, 150, 150);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
t2.start();
}
where clocking is = true. because whenever I press the button. I turn it the clocking to true and then run the startClock().
but as I said before. the digital clock only goes randomly if I change the sleep time below 500. and how can I make it work if it's sleep(1000)?
EDIT NEW ONE:
public void startMoving() {
Thread t1 = new Thread() {
public void run() {
if (moving) {
Random random = new Random();
while (moving) {
int x = random.nextInt(100) + 1;
int y = random.nextInt(100) + 1;
movingDisplay.setBounds(x, y, 150, 150);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
t1.start();
}
public void startClock() {
Thread t2 = new Thread() {
public void run() {
if (clocking) {
Random rand = new Random();
while(clocking){
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
movingClock.setText(hour + ":" + minute + ":" + second);
int x = rand.nextInt(100) + 1;
int y = rand.nextInt(100) + 1;
movingClock.setBounds(x, y, 150, 150);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
movingClock.setText(hour + ":" + minute + ":" + second);
movingClock.setBounds(x, y, 150, 150);
movingDisplay.setBounds(x, y, 150, 150);
}
} );
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
t2.start();
}
I guess you are trying to move your clock on some Swing component like JPanel. You should do all the modifications to the components on an Event Dispatch Thread
Your code should look something like this:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
movingClock.setText(hour + ":" + minute + ":" + second);
movingClock.setBounds(x, y, 150, 150);
}
} );
Look at:
Java Event-Dispatching Thread explanation
I am trying to run a certain task every Friday in a week at any time. So I decided to use ScheduledExecutorService for this but so far I have seen examples which shows how to run task every few minutes.
Below is my code which I adopted to run every day at 5 AM in the morning. How do I use this to run task every Friday in a week at any time?
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
Date aDate = new Date();
Calendar with = Calendar.getInstance();
with.setTime(aDate);
int hour = with.get(Calendar.HOUR_OF_DAY);
int intDelayInHour = hour < 5 ? 5 - hour : 24 - (hour - 5);
System.out.println("Current Hour: " + hour);
System.out.println("Comuted Delay for next 5 AM: " + intDelayInHour);
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
try {
getDataFromDatabase();
} catch (Exception ex) {
ex.printStackTrace(); // or loggger would be better
}
}
}, intDelayInHour, 24, TimeUnit.HOURS);
}
protected static void getDataFromDatabase() {
// TODO Auto-generated method stub
}
Can anyone provide an example how would I do this?
You would have to check what day it is today.
Then set the delay to the next Friday (lets say it is Tuesday, then set a 3 day delay, or use hours if you want to set it at a different time).
And then use a 7 day period (or equivallent in hours).
EDIT:
As requested you can do something like.
Map<Integer, Integer> dayToDelay = new HashMap<Integer, Integer>()
dayToDelay.put(Calendar.FRIDAY, 0);
dayToDelay.put(Calendar.SATURDAY, 6);
dayToDelay.put(Calendar.SUNDAY, 5);
dayToDelay.put(Calendar.MONDAY, 4);
dayToDelay.put(Calendar.TUESDAY, 3);
dayToDelay.put(Calendar.WEDNESDAY, 2);
dayToDelay.put(Calendar.THURSDAY, 1);
int dayOfWeek = with.get(DAY_OF_WEEK);
int delayInDays = dayToDelay.get(dayOfWeek);
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
try {
getDataFromDatabase();
} catch (Exception ex) {
ex.printStackTrace(); // or loggger would be better
}
}
}, delayInDays, 7, TimeUnit.DAYS);
That should run the task every Friday at the time this is executed.
TO RUN PROGRAM EVERY MONDAY AT 11 AM
public static void main(String args[]){
new WeeklyReportService();
}
WeeklyReportService.java
public class WeeklyReportService{
public WeeklyReportService(){
this.startScheduler();
}
private void startScheduler(){
Calendar with = Calendar.getInstance();
Map<Integer, Integer> dayToDelay = new HashMap<Integer, Integer>();
dayToDelay.put(Calendar.FRIDAY, 2);
dayToDelay.put(Calendar.SATURDAY, 1);
dayToDelay.put(Calendar.SUNDAY, 0);
dayToDelay.put(Calendar.MONDAY, 6);
dayToDelay.put(Calendar.TUESDAY, 5);
dayToDelay.put(Calendar.WEDNESDAY, 4);
dayToDelay.put(Calendar.THURSDAY, 3);
int dayOfWeek = with.get(Calendar.DAY_OF_WEEK);
int hour = with.get(Calendar.HOUR_OF_DAY);
int delayInDays = dayToDelay.get(dayOfWeek);
int delayInHours = 0;
if(delayInDays == 6 && hour<11){
delayInHours = 11 - hour;
}else{
delayInHours = delayInDays*24+((24-hour)+11);
}
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(new WeeklyTask(), delayInHours,
179, TimeUnit.HOURS);
}
WeeklyTask.java
Public class WeeklyTask implements Runnable {
#Override
public void run() {
System.out.println("start of weekly report");
/*Your Program to run*/
System.out.println("end of weekly report");
}
}
Hope this helps! You can apply same to any day. In your case, for Friday 11 AM it will be
dayToDelay.put(Calendar.FRIDAY, 6);
dayToDelay.put(Calendar.SATURDAY, 5);
dayToDelay.put(Calendar.SUNDAY, 4);
dayToDelay.put(Calendar.MONDAY, 3);
dayToDelay.put(Calendar.TUESDAY, 2);
dayToDelay.put(Calendar.WEDNESDAY, 1);
dayToDelay.put(Calendar.THURSDAY, 0);
In this code a while loop is supposed to check the time, and if the time is equal to 7 PM, then display a message box.
public void actionPerformed(ActionEvent arg0) {
Enable.setEnabled(false);
Date d = new Date();
int hrs = d.getHours();
int mins = d.getMinutes();
while((1 + 1) == 2) {
if(hrs == 19 && mins == 21) {
JOptionPane.showMessageDialog(frame,
"It's 7:21 PM!",
"Alerts",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
break;
}
}
}
Pushing a button will do that code. If you push the button before it is 7 PM, the GUI will freeze (I don't care about that), and when it turns to 7 PM, it won't display the message box. If you click the button when it is 7 PM, then it will display the message box...
Instead of doing while((1 + 1) == 2) to get an infinite loop, you can just do: while(true) or for(;;)
And this question is unanswerable without any further information or code about your hrs and mins variables
You need to update hrs and mins in your loop otherwise the initialization of them, I assume at the time of pushing the button will always hold the time when the button was pushed.
This is why it works when pushed at 7pm but otherwise will not.
So do something like this
while(true) //Equivalent to what you had
{
if(hrs == 19 && mins == 00) {
JOptionPane.showMessageDialog(frame,
"It's 7:00 PM!",
"Time Alert",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
break;
}
//Refresh your hrs and mins here
Calendar calendar = GregorianCalendar.getInstance(); // Probably dont really want to actually get an instance every time
hrs = calendar.get(Calendar.HOUR_OF_DAY);
mins = calendar.get(Calendar.MINUTE);
}
I'm thinking you're using 1+1=2 to have a continuous loop. you could use while(true){...} instead.
Also, the while loop wouldn't be practical for this case. There is an example on this page that does something similar (Alarm Clock): http://www.ibm.com/developerworks/java/library/j-schedule/index.html
this was their example. I updated it to suite your task.
public class AlarmClock {
private final Scheduler scheduler = new Scheduler();
private final SimpleDateFormat dateFormat =
new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
private final int hourOfDay, minute, second;
public AlarmClock() {
this.hourOfDay = 19;
this.minute = 0;
this.second = 0;
}
public void start() {
scheduler.schedule(new SchedulerTask() {
public void run() {
soundAlarm();
}
private void soundAlarm() {
JOptionPane.showMessageDialog(frame,
"It's 7:00 PM!",
"Time Alert",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
// Start a new thread to sound an alarm...
}
}, new DailyIterator(hourOfDay, minute, second));
}
public static void main(String[] args) {
AlarmClock alarmClock = new AlarmClock();
alarmClock.start();
}
}
Hope it helps.