SWT编程基础-Display和Shell
来源:互联网 发布:数据对接和系统过渡 编辑:程序博客网 时间:2024/05/17 05:06
Display和Shell
首先我们来看一段代码:
package com.gujin.swt;import org.eclipse.swt.SWT;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.Shell;public class HelloSWT{ public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display); Label hello = new Label(shell, SWT.NONE); hello.setBounds(10, 10, 100, 30); hello.setText("Hello SWT"); shell.open(); shell.pack(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); }}
这是一段很简单的示例代码,我们可以将其分为三个部分:
第一部分:创建Display对象
Display display = Display.getDefault();
第二部分:创建并配置Shell
Shell shell = new Shell(display);
Label hello = new Label(shell, SWT.NONE);
hello.setBounds(10, 10, 100, 30);
hello.setText(“Hello SWT”);
shell.open();
shell.pack();
第三部分:进入一个循环
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
这三部分也是一个SWT程序都需要的三部分。
Dispaly的创建
所有的SWT程序在开始运行时都必须获取Display对象,没有Display,SWT程序就无法和操作系统交互,一个SWT程序中至少含有一个Display对象,创建Display对象的线程称为UI线程。
在SWT程序中,我们可以通过如下方式获取一个Display对象:
- new Display:创建一个新的Display实例
- Display.getDefault():第一次调用会创建一个Display对象,之后再次调用会获得之前创建的Display对象,需要注意的是,如果在调用之前已经通过new Display获得了Display对象,那么调用Display.getDefault()将获得之前新创建的Display对象
// 创建一个Display对象
Display create = Display.getDefault();
// 获得Display对象
Display display = Display.getDefault();
// 两次获得对象为同一个
System.out.println(create == display);
这段代码的输出结果为true,同样的下面这段代码也是一样的效果
// 创建一个Display对象
Display create = new Display();
// 获得Display对象
Display display = Display.getDefault();
// 两次获得对象为同一个
System.out.println(create == display);
一个线程中不能同时存在两个活动的Display,如果这样做的话,程序在运行时就会抛出一个SWT异常。如果确实需要创建多个同时活动的Display实例,则必须在不同的线程中创建。我们可以通过Display.getCurrent()函数来获取当前线程对应的Display实例,使用Display.findDisplay(Thread)则可以找到任意线程中的Display对象。
在多线程中,我们不应该使用Display.getDefault()来获得Display实例,这样很容易出现“非法线程访问”的异常,我们可以通过如下方法来获得Display实例:
public static Display getThreadDisplay(){ return Display.getCurrent() == null ? new Display() : Display.getCurrent();}
Shell的创建
在SWT程序中,一个Shell就代表一个窗体,在SWT程序中,为了使资源管理更方便而做了规定,当父资源释放时,它要负责释放属于自己的子资源。从Display直接创建而来的Shell是Display的子资源,而从某个Shell(Shell A)创建而来的Shell B则是Shell A的子资源。当作为父资源的Shell被释放时,作为子资源的Shell也会同时被释放,而由于所有的Shell都是由Display直接或间接创建的,因此Display是所有Shell的最高层父资源,当一个Display被释放时,所有存在于这个UI线程中的Shell窗口都会被释放掉。
Display的事件队列和事件循环
当我们创建了一个窗口并打开它后,就进入事件循环
while (!shell.isDisposed()){ if (!display.readAndDispatch()) { display.sleep(); }}
这段代码就是用于处理事件的循环。通过这段代码我们也可以发现,SWT是通过循环不断的从事件队列中获得信息并处理,所以当我们有耗时较长的事件要处理时,很容易造成程序堵塞,用户的体验度较低,我们通过一段代码来演示一下:
package com.gujin.swt;import org.eclipse.swt.SWT;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.Shell;public class HelloSWT{ public static void main(String[] args) { Display display = Display.getDefault(); Shell shell = new Shell(display); final Label label = new Label(shell, SWT.NONE); label.setBounds(10, 10, 200, 30); label.setText("before"); Button button = new Button(shell, SWT.BORDER); button.setBounds(10, 50, 200, 30); button.setText("deal"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { try { Thread.sleep(10000); } catch (Exception e2) { } label.setText("after"); } }); shell.open(); shell.pack(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); }}
运行这段代码,我们可以发现,当我们点击按钮后,窗口会堵塞无响应,直至事件处理结束,这在实际应用中肯定是不可取的,在Display中为我们提供了syncExec(Runnable r)和asyncExec(Runnable r)来向队列中插入事件,我们可以对上面的代码进行如下修改:
package com.gujin.swt;import org.eclipse.swt.SWT;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.Shell;public class HelloSWT{ public static void main(String[] args) { final Display display = Display.getDefault(); Shell shell = new Shell(display); final Label label = new Label(shell, SWT.NONE); label.setBounds(10, 10, 200, 30); label.setText("before"); Button button = new Button(shell, SWT.BORDER); button.setBounds(10, 50, 200, 30); button.setText("deal"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { new Thread() { @Override public void run() { try { Thread.sleep(10000); } catch (Exception e2) { } display.syncExec(new Runnable() { @Override public void run() { label.setText("after"); } }); } }.start(); } }); shell.open(); shell.pack(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); }}
我们启动一个新的线程来处理耗时较多的逻辑,在处理完成后想时间队列中添加一个事件完成后续操作,这时候我们发现单击按钮后,窗口不会出现之前的阻塞现象,在事件处理完成后Label上的文本同样会被改变。
- SWT编程基础-Display和Shell
- Display和Shell在SWT中的作用
- SWT中的Display 对象和 Shell对象
- SWT中的Display 对象和 Shell对象
- Java界面 SWT 开发基础——Display and Shell
- SWT中 Display 和 Shell的作用简介。。
- SWT中Display和Shell是个什么东东
- SWT编程基础-控件和图形资源
- 【shell】shell 编程基础
- SWT Display 用法
- Shell 脚本编程 基础和细节
- Shell 脚本编程 基础和细节
- Shell基础编程 变量和运算符
- Linux常用命令和Shell编程基础
- shell编程最基础的命令和相关编程
- shell编程之shell基础
- Shell和Shell编程
- Shell编程基础
- 人工智能
- HDU 1754 I Hate It
- nginx反向代理
- js自娱自乐
- AngularJS五特性
- SWT编程基础-Display和Shell
- php中构造函数和析构函数
- leetcode 050 Pow(x, n)
- JDBC CRUD操作
- 设计模式六大原则(6):开闭原则
- DRP总结—JSP+Servlet+JSTL简单介绍
- Windbg、dump分析类资源链接
- ftp上传文件
- Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验