import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.SWT;
public class GUITest3 {
//Declare sections of GUI
private static Shell shell = new Shell();
CLabel sensorTitleLabel = new CLabel(shell, SWT.SHADOW_OUT);
CLabel sensorNum_1 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
CLabel lblBattery = new CLabel(shell, SWT.SHADOW_OUT);
CLabel lblLastAlert = new CLabel(shell, SWT.SHADOW_OUT);
CLabel lblAlert = new CLabel(shell, SWT.SHADOW_OUT);
CLabel batter_1 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
final CLabel lstAlert_1 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
CLabel alert_1 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
CLabel sensorNum_2 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
CLabel battery_2 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
CLabel lstAlert_2 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
CLabel alert_2 = new CLabel(shell, SWT.BORDER | SWT.SHADOW_IN);
public GUITest3()
{
//Default constructor sets up the values for the GUI
shell.setSize(450, 300);
shell.setText("SWT Application");
sensorTitleLabel.setAlignment(SWT.CENTER);
sensorTitleLabel.setBounds(10, 10, 100, 21);
sensorTitleLabel.setText("Sensor Number");
sensorNum_1.setBounds(10, 37, 100, 21);
sensorNum_1.setText("");
lblBattery.setAlignment(SWT.CENTER);
lblBattery.setText("Battery");
lblBattery.setBounds(116, 10, 100, 21);
lblLastAlert.setAlignment(SWT.CENTER);
lblLastAlert.setText("Last Alert");
lblLastAlert.setBounds(222, 10, 100, 21);
lblAlert.setAlignment(SWT.CENTER);
lblAlert.setText("Alert");
lblAlert.setBounds(328, 10, 100, 21);
batter_1.setText("");
batter_1.setBounds(116, 37, 100, 21);
lstAlert_1.setText("");
lstAlert_1.setBounds(222, 37, 100, 21);
alert_1.setText("");
alert_1.setBounds(328, 37, 100, 21);
sensorNum_2.setText("");
sensorNum_2.setBounds(10, 64, 100, 21);
battery_2.setText("");
battery_2.setBounds(116, 64, 100, 21);
lstAlert_2.setText("");
lstAlert_2.setBounds(222, 64, 100, 21);
alert_2.setText("");
alert_2.setBounds(328, 64, 100, 21);
synchronized(this)
{
//Starts the timer, passing in the GUI
new AlertTimer(this).start();
}
}
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
GUITest3 window = new GUITest3();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
public void setTimerLabel(final String timeLeft)
{
//For changing the displayed time
Display.getDefault().asyncExec(new Runnable() {
public void run()
{
lstAlert_1.setText(timeLeft);
}
});
}
}
class AlertTimer {
private static final int TIMER_PERIOD = 1000; //Sounts in one second intervals
protected static final int MAX_COUNT = 300; //Max count, a.k.a. five minutes
private GUITest3 gui;
private int count = 0;
public AlertTimer(GUITest3 screenie) {
gui = screenie;
String text = (count / 60)+":0"+(count % 60);
screenie.setTimerLabel(text);
}
public void start() {
new Timer(TIMER_PERIOD, new ActionListener() {
@Override
public synchronized void actionPerformed(ActionEvent e) {
if (count < MAX_COUNT) {
count++;
String text = "";
if((count % 60) > 9)
{
text = (count / 60)+":"+(count % 60);
}
else
text = (count / 60)+":0"+(count % 60);
System.out.println(text);
gui.setTimerLabel(text);
} else {
//((Timer) e.getSource()).stop();
Display.getDefault().syncExec(new Runnable() {
public void run()
{
synchronized (gui)
{
AlertFlash alrt1 = new AlertFlash(gui);
Thread flashing = new Thread(alrt1);
flashing.start();
}
}
});
}
}
}).start();
}
}
所以,这是一个gui,显示一个计时器并开始计时,当它到达5点时停止(然后做一些事情,但仍在继续工作,我知道它有问题,但我会继续计时在我考虑这个计时器的同时).
由于某些原因我无法弄清楚,计时器偶尔会停止.我有计时器在4:18,0:02,2:13等停止计数,我花了一些时间看看是否有一个模式,看看是否会导致我得出任何结论,但我不能看一个模式.没有错误消息,它只是停止.
我认为这与线程方面有关(我承认,我的知识非常缺乏,仍然存在),可能缺少“同步”或“易变”或类似,我尝试添加并删除奇怪的’同步’/’易变’,我认为这是有道理的,但仍然是同样的问题.
还尝试将AlertTimer代码放在一个单独的类中,实现Runnable并通过不同的Thread运行它,但同样的事情,计时器停止在随机点滴答.
有点想要尝试什么,或者我哪里出错了.希望你们能帮忙!谢谢阅读.
最佳答案 我没有使用SWT,但我想在这种情况下它与Swing或JavaFX非常相似.
您永远不应该在更新队列中执行此操作.这意味着是一个次要的非阻塞操作,否则它可能会阻止进一步的更新,这就是你的情况:
Display.getDefault().syncExec(new Runnable() { // <- try changing it to asyncExec
public void run()
{
synchronized (gui) // <-- try removing this
{
AlertFlash alrt1 = new AlertFlash(gui);
Thread flashing = new Thread(alrt1);
flashing.start();
}
}
});
另一个可能的原因可能是阻止动作执行的syncExec(runnable) – 这也不应该在动作中发生.您可以尝试使用asyncExec(runnable)来避免这种情况.