为什么在使用 runnable 时我的 Java SWT Gui 应用程序的标签没有改变?
Why does the Label not change for my Java SWT Gui application when using a runnable?
所以我现在遇到了一个问题,因为一切都在正常工作,我只是在试验一些代码来创建一个简单的系统时间和日期设置。我有一个问题似乎无法解决。所以我已经确定了一个标签(不是 JLabel),当我尝试通过 运行nable void 运行 它时,当我尝试设置文本以更新系统的确切时间时,它似乎出错了.所以例子 Time.setText(time); time 将被识别为一个字符串,但它只是出错并且不起作用。
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
public class HomeScreen {
protected Shell shell;
private Label Date;
private Label Time;
private Composite composite;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
HomeScreen window = new HomeScreen();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
Date();
Time();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
shell = new Shell();
shell.setSize(450, 300);
shell.setText("Project Serenity");
composite = new Composite(shell, SWT.NONE);
composite.setBounds(0, 0, 470, 278);
Time = new Label(composite, SWT.NONE);
Time.setLocation(10, 192);
Time.setSize(169, 31);
Time.setText("Time");
Date = new Label(composite, SWT.NONE);
Date.setLocation(10, 217);
Date.setSize(169, 38);
Date.setText("Date");
}
public void Date()
{
Thread Date2 = new Thread()
{
@Override
public void run()
{
try {
for(;;){
Calendar cal = new GregorianCalendar();
int day = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
Time.setText(day + ", " + month + " " + year);
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Date2.start();
}
public void Time()
{
Thread Time2 = new Thread()
{
@Override
public void run()
{
try {
for(;;){
Calendar cal = new GregorianCalendar();
int second = cal.get(Calendar.SECOND);
int minute = cal.get(Calendar.MINUTE);
int hour = cal.get(Calendar.HOUR);
int am_pm = cal.get(Calendar.AM_PM);
sleep(1000);
Time.setText(hour + ":" + minute + ":" + second + " " + am_pm);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Time2.start();
}
}
谢谢像素
所有对用户界面对象的访问都必须在用户界面线程中完成。试图在任何其他线程中访问它们将引发异常。
您可以使用Display
的asyncExec
方法在UI线程中执行一个Runnable
。所以不只是做:
Time.setText(day + ", " + month + " " + year);
在您的后台线程中执行:
Display.getDefault().asyncExec(() -> Time.setText(day + ", " + month + " " + year));
以上是针对Java8,如果您使用的是旧版本Java,请使用:
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run {
Time.setText(day + ", " + month + " " + year);
}
});
注意:请学习使用Java命名约定——变量以小写字母开头,因此Time
应该是time
.
退出应用程序时,您也没有做任何事情来停止更新线程。主 UI 线程停止后访问控件将给您一个错误。您可以测试 Time
控件是否已被释放,这将告诉您应用程序已停止。
if (Time.isDisposed()) {
// TODO exit the thread
}
所以我现在遇到了一个问题,因为一切都在正常工作,我只是在试验一些代码来创建一个简单的系统时间和日期设置。我有一个问题似乎无法解决。所以我已经确定了一个标签(不是 JLabel),当我尝试通过 运行nable void 运行 它时,当我尝试设置文本以更新系统的确切时间时,它似乎出错了.所以例子 Time.setText(time); time 将被识别为一个字符串,但它只是出错并且不起作用。
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
public class HomeScreen {
protected Shell shell;
private Label Date;
private Label Time;
private Composite composite;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
try {
HomeScreen window = new HomeScreen();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
Date();
Time();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
shell = new Shell();
shell.setSize(450, 300);
shell.setText("Project Serenity");
composite = new Composite(shell, SWT.NONE);
composite.setBounds(0, 0, 470, 278);
Time = new Label(composite, SWT.NONE);
Time.setLocation(10, 192);
Time.setSize(169, 31);
Time.setText("Time");
Date = new Label(composite, SWT.NONE);
Date.setLocation(10, 217);
Date.setSize(169, 38);
Date.setText("Date");
}
public void Date()
{
Thread Date2 = new Thread()
{
@Override
public void run()
{
try {
for(;;){
Calendar cal = new GregorianCalendar();
int day = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
Time.setText(day + ", " + month + " " + year);
sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Date2.start();
}
public void Time()
{
Thread Time2 = new Thread()
{
@Override
public void run()
{
try {
for(;;){
Calendar cal = new GregorianCalendar();
int second = cal.get(Calendar.SECOND);
int minute = cal.get(Calendar.MINUTE);
int hour = cal.get(Calendar.HOUR);
int am_pm = cal.get(Calendar.AM_PM);
sleep(1000);
Time.setText(hour + ":" + minute + ":" + second + " " + am_pm);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Time2.start();
}
}
谢谢像素
所有对用户界面对象的访问都必须在用户界面线程中完成。试图在任何其他线程中访问它们将引发异常。
您可以使用Display
的asyncExec
方法在UI线程中执行一个Runnable
。所以不只是做:
Time.setText(day + ", " + month + " " + year);
在您的后台线程中执行:
Display.getDefault().asyncExec(() -> Time.setText(day + ", " + month + " " + year));
以上是针对Java8,如果您使用的是旧版本Java,请使用:
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run {
Time.setText(day + ", " + month + " " + year);
}
});
注意:请学习使用Java命名约定——变量以小写字母开头,因此Time
应该是time
.
退出应用程序时,您也没有做任何事情来停止更新线程。主 UI 线程停止后访问控件将给您一个错误。您可以测试 Time
控件是否已被释放,这将告诉您应用程序已停止。
if (Time.isDisposed()) {
// TODO exit the thread
}