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(); } }
时间: 2024-10-11 06:35:31