import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
public class ThirdChapter extends Shell {
private static Text text;
private static List list;
private static Label benefitOfSwtLable;
private static Group group;
private static Button awtButton;
private static Button swingButton;
private static Button swtButton;
private static Button button;
public static void main(String[] args) {
// TODO Auto-generated method stub
final Display display = Display.getDefault(); // 创建Display对象,SWT程序和操作系统交互必须的。一个线程中不能同时有两个活动的Display存在。
final Shell shell = new Shell(display); // 创建一个窗口对象
shell.setText("Hello SWT");
shell.setSize(260, 283); // 设置窗口尺寸
shell.open(); // 打开窗口
// 调用getPrimaryMonitor取得主监视器的信息,如果系统中安装了多个监视器可以用getMonitors方法得到它们
Monitor monitor = display.getPrimaryMonitor();
// 监视器对象主要包含边界和客户区域两个部分。边界代表监视器(整个桌面)的屏幕大小,而客户区域则代表可以用来显示窗口
// 的屏幕部分大小。一般来说,由于图形操作系统桌面上的任务栏占掉了一部分空间,客户区域的尺寸要小于边界的尺寸
System.out.println(monitor.getClientArea());
System.out.println(monitor.getBounds());
text = new Text(shell, SWT.BORDER);
text.setText("SWT是Eclipse平台使用的图形工具箱");
text.setBounds(10, 8, 230, 35);
list = new List(shell, SWT.BORDER);
list.setItems(new String[] { "使用操作系统本地控件", "提供一套平台无关的API",
"GUI程序的运行速度快", "更多更多......" });
list.setBounds(10, 68, 232, 82);
Color createdWhite = new Color(display, 255, 255, 255); // 自己创建一个Color,自己构造的Color对象时,一定要调用它的dispose方法释放在占用的系统资源
Color systemBlack = display.getSystemColor(SWT.COLOR_BLACK); // 从Display中取得一个系统Color,这样取得的Color实例,在使用完毕后不应该调用dispose方法释放
// 它,因为这些实例可能在其他地方被使用到,如果在一处释放掉,其他使用到的地方都会出错,这也符合前面提到的"谁构造谁释放"原则,因为程序只是在使用而没有构造它,所以使用完毕也不应该去释放
Font sysFont = display.getSystemFont();
Font createdTahoma = new Font(display,"Tahoma",10,SWT.BOLD);
Font createdArial = new Font(display,"Arial",12,SWT.ITALIC);
benefitOfSwtLable = new Label(shell, SWT.NONE);
benefitOfSwtLable.setText("SWT的优点:");
benefitOfSwtLable.setBounds(10, 49, 90, 15);
benefitOfSwtLable.setBackground(systemBlack); // 背景色为黑色
benefitOfSwtLable.setForeground(createdWhite); // 前景色为白色
benefitOfSwtLable.setFont(createdTahoma);
group = new Group(shell, SWT.NONE);
group.setText("你使用过哪些图形工具箱");
group.setBounds(10, 159, 230, 47);
awtButton = new Button(group, SWT.CHECK);
awtButton.setText("AWT");
awtButton.setBounds(10, 20, 54, 18);
swingButton = new Button(group, SWT.CHECK);
swingButton.setText("SWING");
swingButton.setBounds(70, 22, 60, 15);
swtButton = new Button(group, SWT.CHECK);
swtButton.setText("SWT");
swtButton.setBounds(136, 22, 62, 15);
Image image = new Image(display, "D:\\fu.png");
Image iconImage = display.getSystemImage(SWT.ICON_QUESTION);
shell.setImage(iconImage);
button = new Button(shell, SWT.NONE);
button.setText("按一下按钮,向SWT说Hello");
button.setBounds(10, 214, 227, 25);
button.setImage(image);
button.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
// 创建一个对话框
// MessageBox msgBox = new MessageBox(shell,
// SWT.ICON_INFORMATION);
// msgBox.setMessage("Hello SWT!");
// msgBox.open();
/**
* SWT采用单线程模型管理绘图操作,只有UI线程才能进行控件重绘和处理事件循环等直接访问Display的操作,
* 非UI线程试图直接操作Display则会导致一个SWT异常。
*
*/
new Thread() {
@Override
public void run() {
try {
Thread.sleep(50000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 后台线程需要将结果显示在界面上时,将绘图操作与UI线程同步,由UI线程在事件循环中执行这些操作
// Display维护了一个自定义的事件队列,这个队列就是用来供后台线程和UI线程同步的。
// 后台线程Runnable将绘图操作包装起来,然后将对象插入事件队列中,这样Display执行消息循环时就会执行这些操作了
// Display提供了两个方法像这个队列 中插入事件:display.syncExec(new
// Runnable()(同步调用)和display.asyncExec(new
// Runnable()(异步调用)
// 注意:常见后台线程时,通常会将需要在Runnable的run()方法中访问的图形界面组件传递过去。但是在代码被UI线程执行时
// 涉及的组件有可能已经被释放了。因此在Runnalbe中需要对所用到的组件的状态加以判断,以防止产生组件已被释放的SWT异常。
display.syncExec(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if (button != null) {
button.setText("Execution done");
}
}
});
}
}.start();
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
}
});
//使用系统托盘
Tray systemTray = display.getSystemTray();
TrayItem newItem = new TrayItem(systemTray, SWT.NONE); //生成一个TrayItem,设置它的图标和提示文字
newItem.setImage(display.getSystemImage(SWT.ICON_ERROR));
newItem.setToolTipText("Test Tray!");
final Menu menu = new Menu(shell,SWT.POP_UP); //创建一个有两个菜单项的菜单
MenuItem item1 = new MenuItem(menu, SWT.PUSH);
item1.setText("Menu Item 1");
MenuItem item2 = new MenuItem(menu, SWT.PUSH);
item2.setText("Menu Item 2");
newItem.addListener(SWT.MenuDetect, new Listener() {
@Override
public void handleEvent(Event event) {
// TODO Auto-generated method stub
menu.setVisible(true);
}
});
shell.layout(); // 布局窗口
// 控件释放
// button.dispose():将按钮控件释放掉。
// 控件也会占用系统资源,这部分资源的分配是在控件的构造函数中完成的。当一个控件的dispose方法被调用后,它所占有的系统资源被
// 释放了,但是这个控件所对应的Java对象依然存在,如果UI线程试图对这个已经被释放的控件进行操作,就会得到“控件已被释放”的异常
// 因此手动释放控件会导致一系列的问题,如果不是万不得已,最好不要手动释放一个控件,而应该交由SWT系统自动释放它们。
// 每个程序都有的消息循环部分
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
//自己创建的对象一定要释放,而使用系统的则不能去释放
createdWhite.dispose();
display.dispose();
image.dispose();
createdArial.dispose();
createdTahoma.dispose();
newItem.dispose();
}
/**
* 开发多UI线程的程序时,推荐使用如下代码来管理Display实例
*
* @return
*/
public static Display getThreadDisplay() {
return Display.getCurrent() == null ? new Display() : Display
.getCurrent();
}
}