我试图制作一个每秒更新一次的简单时钟,以降低CPU的成本。我最初尝试使用Thread.sleep()
,但是当在GUI中的循环中使用时,它基本上冻结了整个事物并导致它崩溃,但没有在控制台中显示任何特定错误。
我查找了其他方式以特定间隔发送命令并遇到了Timer
所以我尝试使用它。现在我有这个代码。
package clock;
import java.util.Timer;
import java.util.TimerTask;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormAttachment;
public class SystemClock {
Text labelHours;
Text labelMinutes;
Text labelSeconds;
Text labelMeridian;
TimerTask time = new TimerTask(){
public void run(){
pullClock();
}
};
boolean pause=false;
Timer play = new Timer();
long delay = 1000;
long period = 1000;
protected Shell shlClock;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
SystemClock window = new SystemClock();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shlClock.open();
shlClock.layout();
while (!shlClock.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
shlClock = new Shell();
shlClock.setSize(205, 118);
shlClock.setText("Clock");
shlClock.setLayout(null);
Label labelColonHoursMinutes = new Label(shlClock, SWT.NONE);
labelColonHoursMinutes.setBounds(64, 10, 9, 15);
labelColonHoursMinutes.setText(":");
Label labelColonMinutesSeconds = new Label(shlClock, SWT.NONE);
labelColonMinutesSeconds.setBounds(96, 10, 9, 15);
labelColonMinutesSeconds.setText(":");
labelMinutes = new Text(shlClock, SWT.NONE | SWT.CENTER);
labelMinutes.setBounds(71, 10, 19, 15);
labelMinutes.setEditable(false);
labelMinutes.setText("00");
labelHours = new Text(shlClock, SWT.NONE | SWT.CENTER);
labelHours.setEditable(false);
labelHours.setBounds(40, 10, 18, 15);
labelHours.setText("00");
labelSeconds = new Text(shlClock, SWT.NONE | SWT.CENTER);
labelSeconds.setBounds(101, 10, 25, 15);
labelSeconds.setEditable(false);
labelSeconds.setText("00");
Button btnRefresh = new Button(shlClock, SWT.NONE);
btnRefresh.setBounds(58, 36, 75, 25);
btnRefresh.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
pause= !pause;
if (pause)
try{
play.scheduleAtFixedRate(time, delay, period);
}catch(Exception ex){
}
else
play.cancel();
}
});
btnRefresh.setText("Pause/Play");
labelMeridian = new Text(shlClock, SWT.NONE);
labelMeridian.setBounds(125, 10, 25, 15);
labelMeridian.setEditable(false);
labelMeridian.setText("AM");
}
public void pullClock(){
long currentTime = System.currentTimeMillis();
int hours;
int minutes;
int seconds;
String hoursStr;
String minutesStr;
String secondsStr;
String meridian;
currentTime/=1000;
seconds = (int)currentTime%60;
currentTime/=60;
minutes = (int)currentTime%60;
currentTime/=60;
hours = (int)currentTime%24;
hours -=4;
switch(hours){
case -4: hoursStr="8"; meridian = "PM"; break;
case -3: hoursStr="9"; meridian = "PM"; break;
case -2: hoursStr="10"; meridian = "PM"; break;
case -1: hoursStr="11"; meridian = "PM"; break;
case 0: hoursStr="12"; meridian = "AM"; break;
case 12: hoursStr="12"; meridian = "PM"; break;
case 13: hoursStr="1"; meridian = "PM"; break;
case 14: hoursStr="2"; meridian = "PM"; break;
case 15: hoursStr="3"; meridian = "PM"; break;
case 16: hoursStr="4"; meridian = "PM"; break;
case 17: hoursStr="5"; meridian = "PM"; break;
case 18: hoursStr="6"; meridian = "PM"; break;
case 19: hoursStr="7"; meridian = "PM"; break;
default: hoursStr=String.valueOf(hours); meridian = "AM";
}
secondsStr=String.valueOf(seconds);
minutesStr=String.valueOf(minutes);
labelHours.setText(hoursStr);
labelMinutes.setText((minutes<10) ? "0"+minutesStr:minutesStr);
labelSeconds.setText((seconds<10) ? "0"+secondsStr:secondsStr);
labelMeridian.setText(meridian);
}
}
这会导致org.eclipse.swt.SWTException
并导致程序崩溃。
我正在使用Eclipse,它很容易获得SWT gui编辑器来构建程序,它似乎是问题的一部分。我的问题基本上是,如果有一种方法可以在使用SWT时修复它,如果不是,那么如果我使用JFrame
会这样吗?
答案 0 :(得分:3)
您正在寻找的内容在SWT中称为Display#timerExec()
。该方法接受一个runnable,它将在经过一定量的毫秒后执行一次。
display.timerExec( 1000, new Runnable() {
public void run() {
if( !shlClock.isDisposed() {
pullClock();
display.timerExec( 1000, this );
}
}
}
在上面的代码段中,runnable在实际工作完成后重新调度itslef(display.timerExec( 1000, this );
)。
要取消已安排的runnable,请致电display.timerExec( -1, runnable )
。
答案 1 :(得分:2)
使用其他答案中提到的display.timerExec
可能是最好的,但您也可以在计时器任务中使用Display.syncExec
:
TimerTask time = new TimerTask() {
public void run() {
Display.getDefault().synchExec(new Runnable() {
public void run() {
pullClock();
}
});
}
};
或者如果您使用的是Java 8,则可以将其简化为:
TimerTask time = new TimerTask() {
public void run() {
Display.getDefault().synchExec(() -> pullClock());
}
};