图形

SWT 提供了图形引擎以在窗口小部件中绘图和显示图像。即使以前没有为图形界面编程,您也可以做得相当好,原因是窗口小部件负责处理图标、文本和其它数据的绘制。但是,如果您的应用程序显示定制图形,或者如果您正在实现定制绘制的窗口小部件,则将需要了解 SWT 中的一些基本绘图对象。

图形环境

图形环境 GC 是 SWT 图形支持的焦点。它的 API 描述 SWT 中的所有绘图功能。

GC 可用于在控件(这是最常见的情况)、图像、屏幕或打印机上绘图。当在控件上绘图时,使用在控件的绘图事件中为您提供的 GC。当在图像、屏幕或打印机上绘图时,必须创建为它配置的 GC,并在使用完它时除去 GC。

一旦获得了 GC,您就可以设置它的属性,例如,颜色、行宽和字体,它们控制在 GC 中绘制的图形的外观。

GC 的“API 参考”描述一组完整的图形功能。

字体

当处理 SWT 中的字体时,使用字体FontData 类。

FontData 描述字体的特征。可以通过指定字体名、样式和大小来创建 FontData。FontData 包含用于查询这些属性的 API。由于 FontData 不分配任何操作系统资源,因此不需要除去它。

Font 是表示在绘图 API 中使用的字体的实际图形对象。通过指定想要的字体的 Display 和 FontData 来为 Display 创建 Font。也可以通过查询 Font 来获取它的 FontData。

当使用完已分配的 Font 时,必须除去它。

颜色

颜色的处理与字体是相似的。通过为期望的颜色指定 RGB 值来为 Display 创建 Color。当使用完已分配的颜色时,必须除去它。

Display 方法 getSystemColor(int) 允许您查询操作系统平台的预定义系统颜色。不应该释放使用此技术所获得的颜色。

SWT 颜色模型这篇文章中详细讨论了颜色模型。

图像

在 SWT 中处理图像时,使用 ImageImageDataImageLoader 类。

ImageData 描述图像中的实际像素,使用 PaletteData 类来描述所使用的颜色值。ImageData 是一个图像的独立于设备和平台的描述。

ImageLoader 以不同的文件格式来装入和保存 ImageData。SWT 当前支持装入和保存包括 BMP(Windows 位图)、ICO(Windows 图标)、JPEGGIFPNG 在内的图像格式。

Image 是表示在绘图 API 中使用的图像的实际图形对象。为特定的 Display 创建图像。可以采用几种方法来创建图像:

不管您如何创建 Image,您都要负责除去它。

图形对象生命周期

用于在 SWT 中绘图的大多数图形对象在底层操作系统中分配资源,并且必须显式地释放这些对象。先前讨论的那些规则在此处也适用。如果使用构造函数来创建它,则应该释放它。如果是从其它地方获得它的,则不要释放它。

创建

只要创建了对象,就在操作系统中分配图形对象,例如,图形环境、字体、颜色和图像。您计划使用图形对象的方式确定创建它们的时间。

对于在整个应用程序中大量使用的图形对象,可以在创建窗口小部件时创建它们。这通常是针对颜色和字体。在其它情况下,更适合即时创建图形对象。例如,可以在其中一个窗口小部件事件处理程序中创建图形环境以便执行某些计算。

如果您正在实现定制窗口小部件,则通常在构造函数中分配图形对象(如果您始终要使用它们)。如果不是要一直使用它们,或者它们依赖于某些属性的状态,则可以即时分配它们。

绘制

一旦已经分配了图形对象,就可以开始绘制了。始终应当在绘制侦听器内部进行绘制。很少情况下(特别是在实现定制窗口小部件时)要在绘制的同时响应其它某些事件。但是,这通常让人泄气。如果您认为需要在绘制的同时处理其它某些事件,则应该首先尝试使用 redraw() 方法,该方法将在操作系统中生成另一个绘制事件。在绘制方法外部进行绘图将使平台优化失效,并且可能会导致故障,这取决于事件队列中暂挂绘制的数目。

当接收到绘制事件时,将为您提供预先配置的 GC 用于在窗口小部件中绘图。不要释放此 GC!您未创建它。

在处理事件时(或之前)必须分配所有其它图形对象。以下是基于 org.eclipse.swt.examples.HelloWorld5 样本的代码段。先前在创建窗口小部件时已分配了红色,因此,在此处可以使用这种颜色。

   shell.addPaintListener(new PaintListener () {
      public void paintControl(PaintEvent event){
         GC gc = event.gc;
         gc.setForeground(red);
         Rectangle rect = event.widget.getClientArea();
         gc.drawRectangle(rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20);
         gc.drawString(resHello.getString("Hello_world"), rect.x + 20, rect.y + 20);
      }
   });

除去

使用完您分配的每个图形对象时,必须释放它。

处理的时间取决于您是何时创建对象的。如果在创建窗口小部件的同时创建图形对象,则通常应该将除去侦听器添加到窗口小部件上,并在除去窗口小部件时除去图形。如果您在绘制时即时创建对象,则应该在完成绘图时除去它。

下面的代码段说明绘制侦听器的稍作修改后的版本。在此示例中,它在绘图时分配和释放红色。

   shell.addPaintListener(new PaintListener () {
      public void paintControl(PaintEvent event){
         GC gc = event.gc;
         Color red = new Color(event.widget.getDisplay(), 0xFF, 0, 0);
         gc.setForeground(red);
         Rectangle rect = event.widget.getClientArea();
         gc.drawRectangle(rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20);
         gc.drawString(resHello.getString("Hello_world"), rect.x + 20, rect.y + 20);
         red.dispose();
      }
   });