
可以使用标准窗口小部件工具箱(Standard Widget Toolkit SWT)和 JFace 库来开发用于 Eclipse 环境的图形用户界面 而且还可以将它们用于开发单独的 GUI 本机应用程序 在本文中 我将介绍一些基本的 SWT(基本 GUI 对象的名称)类型 并展示如何综合使用它们来创建有用的应用程序 关于 Eclipse SWT 和 JFace 正如 Eclipse 的 Web 站点上所提到的 Eclipse 是一种通用工具平台 它是一个开放的 可用于任何东西的可扩展 IDE 没什么特别之处 它为工具开发人员提供了灵活性以及对软件技术的控制 Eclipse 为开发人员提供了生产大量 GUI 驱动的工具和应用程序的基础 而这项功能的基础就是 GUI 库 SWT 和 JFace SWT 是一个库 它创建了Java 版的本地主机 *** 作系统 GUI 控件 它依赖于本机实现 这意味着基于 SWT 的应用程序具有以下几个关键特性 它们的外观 行为和执行类似于 本机 应用程序 所提供的窗口小部件(widget)反映了主机 *** 作系统上提供的窗口小部件(组件和控件) 主机 GUI 库的任何特殊行为都在 SWT GUI 中得到反映 这些目标使得 SWT 不同于 Java 技术的 Swing Swing 的设计目标是消除 *** 作系统的差异 SWT 库反映了主机 *** 作系统的基本窗口小部件 在许多环境下 这种方法太低级 JFace 库有助于向 SWT 应用程序中添加大量服务 JFace 并没有隐藏 SWT 它只是扩展了 SWT 正如您将在这一系列的后面部分中看到的 SWT 最重要的扩展之一是 将应用程序的数据模型与显示及更改它的 GUI 隔离开来 在开始之前 我需要介绍一些 SWT 术语 Widget —— 基本的 SWT GUI 组件(类似于 Java AWT 中的 Component 和 Swing 中的 JComponent) Widget 是一个抽象类 Control —— 拥有 *** 作系统的对等物的窗口小部件(换句话说 在 *** 作系统中具有同一身份) Control 是一个抽象类 Composite —— 包含其他控件的控件(类似于 Java AWT 中的 Container 和 Swing 中的 JPanel) Item —— 其他控件包含的窗口小部件(该控件可能不是复合控件) 比如列表和表 注意 包含一些项的控件很少包含其他控件 反之亦然 Item 是一个抽象类 这些窗口小部件被安排在继承层次结构中 参见图 图 和图 了解它们是如何安排的 在图 中 Basic 类是来自本文的类 而其他所有类都是标准的 SWT 窗口小部件 图 SWT Widget 树 图 SWT Composite 树 图 SWT Item 列表
注意 Eclipse 具有跨平台特性(因此可以在许多 *** 作平台上运行) 本文基于 Eclipse 的 Microsoft Windows 版本 因此 本文包含的每个例子都应该能够不加任何更改地在其他平台上使用 还要注意的是 本文是基于 Eclipse V 的 Eclipse V 中添加了少许 GUI 窗口小部件类型和特性 基本控件 几乎所有 SWT GUI 都是从某些基础部分开始创建的 所有 SWT 窗口小部件都可以在 eclipse swt widget 或 eclipse swt custom 包中找到 (一些 Eclipse 插件还在其他包中提供了定制的窗口小部件 )窗口小部件包中包含一些基于 *** 作系统控件的控件 而定制包中则包含一些超出 *** 作系统控件集之外的控件 一些定制的软件包控件类似于窗口小部件包中的控件 为了避免命名冲突 定制控件的名称都是以 C 开始的(例如 比较 CLabel 与 Label) 在 SWT 中 所有控件(除了一些高级控件 比如 shell 将在后面进行讨论)在创建的时候都必须有一个父控件(一个复合实例) 在创建的时候 这些控件被自动 添加 到父控件中 这与必须明确添加到父控件中的 AWT/Swing 中的控件有所不同 自动添加产生了一种 自上而下 地构造 GUI 的方法 这样 所有控件都可以采用一个复合父控件(或者一个子类)作为构造函数的参数 大多数控件都有一些必须在创建时设置的标记选项 因此 大多数控件还有另外一个构造函数参数 我们通常称之为样式 该参数提供了设置这些选项的标记 所有这些参数值都是 static final int 并且都是在 eclipse swt 包的 SWT 类中定义的 如果不需要任何参数 则可以使用 SWT NONE 值 标签 标签可能是最简单的控件 标签 被用于显示纯文本(没有颜色 特殊字体或样式的文本)或称为图标的小图像 标签不接受焦点(换句话说 用户不能通过 Tab 键或鼠标移动到标签) 因此 标签无法产生输入事件 清单 展示了如何创建一个简单的文本标签 清单 创建一个带文本的标签import eclipse swt widget ;:Composite parent = ;:// create a center aligned labelLabel label = new Label(parent SWT CENTER);label setText( This is the label text );注意 该文本是采用不同于构造函数的单独的方法设置的 这是所有 SWT 控件的一个典型象征 只有父控件和样式是在构造函数中设置的 其他所有属性都是在已创建的对象上设置的 由于平台的限制 标准标签控件不能同时拥有文本和图标 为了支持同时拥有文本和图标 可以使用 CLabel 控件 如清单 中所示 清单 创建一个包含文本和图像的标签import eclipse swt graphics ;import eclipse swt widget ;import eclipse swt custom ;:Composite parent = ;Image image = ;:// create a left aligned label with an iconCLabel Clabel = new CLabel(parent SWT LEFT);label setText( This is the imaged label text );label setImage(image);
文本 在标签显示文本的同时 您时常还想允许用户插入文本 文本 控件就是用于此目的的 文本可以是单行的(一个文本字段) 也可以是多行的(一个文本区域) 文本还可以是只读的 文本字段中没有描述 因此 常常通过标签控件处理它们 以确定它们的用途 文本控件还可以包含一个 工具提示 提供关于控件用途的信息(所有控件都支持这一特性) 清单 显示了如何使用允许使用的有限数量的特性来创建一个简单的文本字段 选择默认文本是为了便于擦除 清单 创建一个包含选定的默认文本和一个限制条件的文本import eclipse swt widget ;:Composite parent = ;:// create a text fieldText name = new Text(parent SWT SINGLE);name setText( <none> );name setTextLimit( );name setToolTipText( Enter your name Last First );name selectAll(); // enable fast erase 按钮 通常 您希望用户指出应该何时进行某项 *** 作 最常见的做法是使用按钮 控件 存在以下几种样式的按钮 ARROW —— 显示为一个指向上 下 左 右方向的箭头 CHECK —— 已标记的复选标记 FLAT —— 没有凸起外观的按钮 PUSH —— 瞬时按钮(最常见的事件源) RADIO —— 具有排他性的粘性标记(sticky mark) 其他所有单选按钮都在相同的组中 TOGGLE —— 一个粘性按钮 清单 创建了一个 Clear 按钮 清单 创建一个按钮import eclipse swt widget ;:Composite parent = ;:// create a push buttonButton clear = new Button(parent SWT PUSH);clear setText( Clea&r );名称中的 & 导致利用紧接着的一个字母创建一个加速 允许通过 Ctrl+<字母> 顺序的方式按下按钮(控件顺序由主机 *** 作系统决定) 事件监听器 通常 您可能想在选择按钮(特别是某种推式按钮)的时候执行一些 *** 作 您可以通过向该按钮添加一个 SelectionListener(在 eclipse swt events 包中)做到这一点 当按钮状态发生改变时(通常是按钮被按下) 就会生成事件 清单 在单击 Clear 按钮时输出一条消息 清单 按钮事件处理程序import eclipse swt events ;:// Clear button pressed event handlerclear addSelectionListener(new SelectionListener() {public void widgetelected(selectionEvent e) {System out println( Clear pressed! );}public void widgetDefaultSelected(selectionEvent e) {widgetelected(e);}});此代码使用了一个匿名的内部类 但您还可以使用指定的内部类或单独的类作为监听器 多数包含两个或更多方法的 Listener 类还有一个类似的 Adapter 类 这个类提供了一些空的方法实现 并且可以减少您需要编写的代码数量 例如 还有一个 SelectionAdapter 类 这个类实现了 SelectionListener 注意 在这些方法中执行的 *** 作必须快速完成(通常不足一秒时间) 或者说 GUI 的反应将是迟钝的 更长时间的 *** 作(比如访问文件)需要单独的线程 但那是以后某期文章的主题
复合控件 至此 我们已经讨论了一些单独的控件 在多数 GUI 中 许多控件被组合在一起以提供丰富的用户体验 在 SWT 中 这种组合是通过 Composite 类实现的 复合控件可以在任何级别上进行嵌套 并且可以混合和匹配控件 将它们作为子控件进行组合 这样做可以极大地减少 GUI 开发的复杂性 并为 GUI 代码重用(通过封装内部 GUI)创造了机会 复合控件可以是有边界的 并且这些边界很容易在视觉上产生混淆 或者它们也可以是无边界的 无缝集成到更大的组中 清单 创建一个有边界的复合控件 单 创建一个有边界的复合控件
import eclipse swt widget ; : Composite parent = ; : Composite border = new Composite(parent SWT BORDER);
除了边界之外 Group 复合子类还支持标题 在定义排他性按钮集合时 组通常被用来包含单选类型的按钮 清单 创建了一个有边界的组 清单 创建一个有边界的组
import eclipse swt widget ; : Composite parent = ; : Group border = new Group(parent SWT SHADOW_OUT); border setText( Group Description );
shell shell 是一种可能没有父复合控件的复合控件(框架或窗口) 此外 它还有一个作为父控件的 Display 这通常也是默认设置 shell 有很多种样式 但最常见的样式是 SWT SHELL_TRIM 或 SWT DIALOG_TRIM shell 可以是模态的 也可以是非模态的 模态 shell 常常用于对话框 防止父 GUI(如果有的话)在关闭子 shell 之前被处理 清单 创建了一个框架样式的顶级非模态 shell 清单 创建一个顶级 shell
import eclipse swt widget ; : Shell frame = new Shell(SWT SHELL_TRIM); :
shell 可以有子 shell 这些子 shell 是与父 shell 相关的独立桌面窗口(也就是说 如果父 shell 关闭 那么其所有子 shell 也将关闭) 清单 创建了一个对话框样式的子 shell 清单 创建一个对话框 shell
: Shell dialog = new Shell(frame SWT DIALOG_TRIM); :
参见图 中具有 SWT SHELL_TRIMSee 的 shell 以及图 中具有 SWT DIALOG_TRIM 的 shell 了解这些值如何影响 shell 的整洁性 图 具有 SWT SHELL_TRIM 的 shell图 具有 SWT DIALOG_TRIM 的 shell
布局管理器 复合控件常常包含多个控件 可以使用以下两种方法安排这些控件 绝对定位 —— 为每个控件设置明确的 X 和 Y 位置 并通过代码设置一定的宽度和高度 托管定位 —— 每个控件的 X Y 宽度和高度都是通过LayoutManager 设置的
在多数情况下 应该选择使用 LayoutManagers 因为很容易调整它们来适应可变大小的 GUI SWT 也提供了一些布局管理器供您使用 在这一期的系列文章中 我们将讨论两种基本的布局管理器 FillLayout 和 GridLayout 在这两种情况下 每当重新设置复合控件的大小 都需要进行定位 一些布局管理器常常是专为某一个复合控件分配的 一些布局管理器只使用它们自身的参数就可以控制 而另一些布局管理器还需要其他参数 —— LayoutData 该参数是在它们管理的复合控件中的每个控件上指定的 FillLayout FillLayout 以行或列的形式安排控件 每个控件所设置的大小将与填充该复合控件所需的宽度和高度相同 在这些控件之间 空间是平均分配的 一种特殊情况是 在仅有一个子控件时 该控件的大小被设置为填充整个父复合控件的大小 清单 使用 FillLayout 创建一列控件
import eclipse swt widget ; import eclipse swt layouts ; : Composite posite = ; FillLayout fillLayout = new FillLayout(SWT VERTICAL); posite setLayout(fillLayout);
GridLayout GridLayout 提供了一个功能更强大的布局方法 该方法类似于使用 HTML 表的方法 它创建了 D 网格的单元格 可以将控件放置在一个或多个单元格中(可以称之为单元格跨越) 单元格的大小可以是相等的 或者是网格宽度或高度的某个给定可变百分比 可以将控件添加到某一行的下一个可用列中 如果这一行中没有更多的列 那么该控件将移动到下一行的第一列中 清单 创建了一个复合控件 该控件有两行和两个列 其中包含两个已标记的文本字段 这些列可以有不同的宽度 清单 创建一个控件表
import eclipse swt widget ; import eclipse swt layouts ; : Composite posite = ; GridLayout gridLayout = new GridLayout( false); posite setLayout(gridLayout); Label l = new Label(posite SWT LEFT); l settext( First Name: ); Text first = new Text(posite SWT SINGLE); Label l = new Label(posite SWT LEFT); l setText( Last Name: ); Text last = new Text(posite SWT SINGLE);
GridData 考虑一下这种情况 您需要指定每个控件如何使用其单元格中的剩余空间 为了给每个单元格提供这种精确控制 添加到 GridLayout 的托管复合控件的控件可以拥有 GridData 实例(LayoutData 的子类) 清单 设置了这些文本字段 以便采用所有可用的剩余空间(根据前面的清单) 清单 配置一个扩展到所有可用空间的布局
first setLayoutData(new GridData(SWT FILL SWT FILL true true)); last setLayoutData(new GridData(SWT FILL SWT FILL true true));
下面是在一个格中加两个按钮的例子,一个在左边,一个在右边,三个图标的只要在加一个就行,可以把 delEditorhorizontalAlignment = SWTLEFT设为CENTER:
TableEditor delEditor = new TableEditor(table_translate);
delEditorhorizontalAlignment = SWTLEFT;//按钮在单元格中的位置,有LEFT、CENTER、RIGHT
delEditorminimumWidth = 75;//按钮的大小
Button deleteBut = new Button(table_translate, SWTNONE);//table_translate是Table类型对象,即要在上面画按钮的那个表格
deleteButsetText("删除");//按钮显示的文字,也可以使用,用deleteButsetImage();方法
delEditorsetEditor(deleteBut, item, 2);//指定按钮deleteBut在TableITem(即item,表格行)的第二列,从0开始
itemsetData(UIConstantsEDITOR_BUTTON_DELETE, deleteBut);
deleteButaddSelectionListener(new DeleteButtonListener(item));//按钮对应的 *** 作,//DeleteButtonListener是继承自SelectionAdapter的类,在该类中的widgetSelected方法中写该按钮具体的 *** 作
TableEditor delEditor1 = new TableEditor(table_translate);
delEditor1horizontalAlignment = SWTRIGHT;
delEditor1minimumWidth = 75;
Button deleteBut1 = new Button(table_translate, SWTNONE);
deleteBut1setText("添加");
delEditor1setEditor(deleteBut1, item, 2);
itemsetData(UIConstantsEDITOR_BUTTON_DELETE, deleteBut1);
deleteBut1addSelectionListener(new DeleteButtonListener(item));//按钮对应 *** 作
效果图如下:
姓名:吴兆阳 学号:14020199009
转自机器人学习研究会
嵌牛导读:OCR(Optical Character Recognition,光学字符识别)的概念早于1920年代便被提出,一直是模式识别领域中重要的研究方向。近年来,随着移动设备的快速更新迭代,以及移动互联网的快速发展,使得OCR有更为广泛的应用场景,从以往的扫描文件的字符识别,到现在应用到自然场景中文字的识别,如识别身份z、yhk、门牌、票据及各类网络中的文字。
嵌牛鼻子:ORC技术
嵌牛提问:什么是ORC,如何使用?
嵌牛正文:
以深度学习兴起的时间为分割点,直至近五年之前,业界最为广泛使用的仍然是传统的OCR识别技术框架,而随着深度学习的崛起,基于这一技术的OCR识别框架以另外一种新的思路迅速突破了原有的技术瓶颈(如文字定位、二值化和文字分割等),并已在工业界得到广泛应用。
笔者针对业务中的身份z照片文字识别需求分别尝试了传统OCR识别框架及基于深度学习的OCR识别框架。下面就以身份z文字识别为例分别简要介绍两种识别框架。
传统OCR技术框架
如上图所示,传统OCR技术框架主要分为五个步骤:
首先文本定位,接着进行倾斜文本矫正,之后分割出单字后,并对单字识别,最后基于统计模型(如隐马尔科夫链,HMM)进行语义纠错。可按处理方式划分为三个阶段:预处理阶段、识别阶段和后处理阶段。其中关键在于预处理阶段,预处理阶段的质量直接决定了最终的识别效果,因此这里详细介绍下预处理阶段。
预处理阶段中包含了三步:
定位中的文字区域,而文字检测主要基于连通域分析的方法,主要思想是利用文字颜色、亮度、边缘信息进行聚类的方式来快速分离文字区域与非文字区域,较为流行的两个算法分别是:最大极值稳定区域(MSER)算法及笔画宽度变换(SWT)算法,而在自然场景中因受到光照强度、拍摄质量和类文字背景的干扰,使得检测结果中包含非常多的非文字区域,而目前从候选区域区分出真正文字区域主要两种方法,用规则判断或轻量级的神经网络模型进行区分;
文本区域图像矫正,主要基于旋转变换和仿射变换;
行列分割提取出单字,这一步利用文字在行列间存在间隙的特征,通过二值化并在投影后找出行列分割点,当在文字与背景的区分度较好时,效果很好,而拍摄的中光照、摄像质量的影响,并且文字背景难以区分时,常造成错误分割的情况。
下面介绍基于传统OCR框架处理身份z文字识别:
身份z识别技术流程与上述框架稍微有所差异。对该问题,已知先验信息:a证件长宽固定;b字体及大小一致;c文本相对于证件位置固定;d存在固定文字。因此,处理该问题的思路为:先定位目标物体(证件),矫正后提取文字进行识别,最后进行语义纠错,如下图:
目标物体定位并矫正。基于现有的先验信息,定位最后的方法为采用模板关键点特征匹配的方法,并利用模板上特征点及目标图像特征点坐标之间的关系进行透视变换,以定位目标物体,如下图所示。接着,基于四角的坐标,进行旋转、仿射、尺寸的变换,并提取出目标物体的俯视图。
因文字位置相对固定,接着便分割出文字区域,二值化后,行列分割出单个字符。这里的技术难点在于二值化,二值化效果的好坏直接影响字符分割,并最终影响识别结果。受光照和拍摄质量的影响,全局二值化难以设置统一的阈值,而自适应二值化算法易受到阴影及模糊边界的干扰。所以在这边尝试过许多方法,测试下来未发现在任何情形下效果都满足要求的方法。
分割出单字后接着用分类器进行识别,并在这步基于统计上的先验信息定义了一个简单的优化函数,可看做1-gram语言模型。先验信息为:2400(总共660273)汉字的使用频率之和为99%以上。定义的优化函数为:
式中,Pi为该字出现的概率,confi为置信度值。
下图给出了示例:
因上述的优化过程中假定各状态相互独立并与上一状态没有联系,故不可避免存在语义上的错误。而如何基于现有的输出序列,对序列进行语义上的修正,那么最直观的想法就是用隐马尔可夫模型(Hidden Markov Model,HMM)解决这个问题,其基于观察序列,求出最优隐序列。其可以抽象为如下图的过程。在给定O序列情况下,通过维特比算法,找出最优序列S:
传统OCR冗长的处理流程以及大量人工规则的存在,使得每步的错误不断累积,而使得最终识别结果难以满足实际需求。接下来讨论基于深度学习的OCR。
基于深度学习的OCR识别框架
目前,从技术流程上来说,主要分为两步,首先是检测出图像中的文本行,接着进行序列识别。 可见,基于深度学习的OCR识别框架相比于传统OCR识别框架,减少了三个步骤,降低了因误差累积对最终识别结果的影响。
文本行检测,其又可分为水平行文字检测算法与倾斜文字行检测算法。这里主要介绍下Tian提出算法CTPN,其算法框架如下图。主要思路是将文本行识别看做一个序列识别问题,不同于一般的目标检测问题,引入RNN来利用上下文的信息。
具体流程为:
用VGG16的5个卷积层得到特征图(feature map,WHC);
在Conv5的feature map的每个位置上取33C的窗口的特征,这些特征将用于预测该位置k个anchor(anchor的定义和Faster RCNN类似)对应的类别信息,位置信息;
将每一行的所有窗口对应的33C的特征(W33C)输入到RNN(BLSTM)中,得到W256的输出;
将RNN的W256输入到512维的fc层;
fc层特征输入到三个分类或者回归层中。第二个2k scores 表示的是k个anchor的类别信息(是字符或不是字符)。第一个2k vertical coordinate和第三个k side-refinement是用来回归k个anchor的位置信息。2k vertical coordinate表示的是bounding box的高度和中心的y轴坐标(可以决定上下边界),k个side-refinement表示的bounding box的水平平移量。这边注意,只用了3个参数表示回归的bounding box,因为这里默认了每个anchor的width是16,且不再变化(VGG16的conv5的stride是16)。回归出来的box如Fig1中那些红色的细长矩形,它们的宽度是一定的;
用简单的文本线构造算法,把分类得到的文字的proposal(图Fig1(b)中的细长的矩形)合并成文本线。
上图为给出基于CTPN的例子,框线部分是算法识别出的文字行,可见在光照不均、人工合成及文字背景对比不明显的情形下均有很好的效果。 相比于传统文字定位方法,具有更好的鲁棒性及明显的优势。
文字行识别。近两年比较受关注的主要有两种,一种是CNN+RNN+CTC的方法,另外一种是用attention model+CNN+RNN的方法。这里主要介绍下CNN+RNN+CTC,算法框架由图给出。分为三层,CNN层、RNN层及解码(transcription)层。在CNN层,用于提取图像特征,利用Map-to-Sequence表示成特征向量;在RNN层,用双向LSTM识别特征向量,得到每列特征的概率分布;在解码层,利用CTC和前向后向算法求解最优的label序列。因此,该方法能够识别不定长的文字行。
两个例子:
Out:辽宁省长海县广鹿乡沙尖
Out:河南省邓州市九龙乡姚营
1、在eclipse中新建一个swt-java项目,项目名字为javashell。
2、在项目中新建一个application window窗口。
3、运行项目,shell窗口在系统默认的位置显示出来,下一步让窗口居中显示。
4、找到createContents这个方法,得到屏幕的宽度。
5、在这个方法中,得到屏幕的高度。
6、得到屏幕的宽高度减去shell窗口的宽度和高度,除以2得到窗口的左上角坐标。设置shell的左上角坐标, 运行项目,窗口居中显示。
现在基于 Eclipse 的应用越来越多 很多桌面应用都是用Eclipse开发的 Eclipse提供了一套 SWT/JFACE 的控件库 使得人们开发界面应用极大的方便 但是 SWT/JFACE的控件库毕竟有限 在应用开发是我们不可避免地要自己开发一些自定义的控件 本文通过开发一个颜色列表控件的实例介绍了Eclipse自定义控件开发中所要用到的技术 目标读者必须熟悉Java开发 并且有一定的Eclipse开发经验 在Eclipse网站上有一篇相关的文章 Creating Your Own Widgets using SWT 该文介绍了开发自己控件的很多基本概念 方法 并且通过实例进行了介绍 非常好 但是其所用的实例比较简单 还有很多控件开发中所要涉及到的内容 例如键盘 鼠标事件的处理 滚动条 焦点的处理等等没有提及 本文通过开发一个自定义的颜色列表控件的实例 全面地介绍了自定义控件所涉及的技术 同时 读者也可以对该实例进行扩展 实现自己的列表控件 SWT中提供的标准列表控件非常简单 只能提供字符串的选择 我们经常需要提供一些图形列表供用户选择 这就需要自己开发自定义的列表控件 颜色选择列表是我们常用的一种图形列表 我们就以此为例进行介绍 以下是我们将要开发的颜色列表 我们在开发自定义控件时主要考虑以下问题 自定义控件的绘制 通常我们需要自己对控件的形状或图案进行绘制 控件对键盘事件的响应 当焦点进入控件 用户进行键盘 *** 作 通过键盘对控件进行控制时 我们需要让控件对用户的 *** 作进行响应 例如在列表中 用户会通过上下箭头改变列表的选择项 控件对鼠标事件的响应 当用户用鼠标选中控件 进行 *** 作时 控件必须作出相应的反应 控件对焦点事件的响应 当界面焦点进入或移出控件 通常我们需要将控件绘制成得到或失去焦点的形状 例如 当焦点进入列表时 一般被选中的列表项会有虚框表示选中 响应TAB键 对于一个可 *** 纵的控件 用户可以用TAB键将焦点移入或移出 响应滚动条事件 当控件有滚动条时 我们需要响应用户对滚动条的 *** 作 完成对控件的绘制工作 提供事件监听机制 程序员使用你的控件时通常需要监听控件中发生的一些事件 这样当事件发生时 他们能够进行相应处理 提供辅助功能(Accessibility) 辅助功能是方便残障人士使用时必须的 标准控件都会提供相应的支持 我们自定义的控件也不例外 提供功能接口方便程序员访问 通常为方便程序员使用时获取控件中的信息或进行设置 我们需要提供一些接口 首先我们要开发的列表控件是一个基本控件 所以我们选择Canvas作为我们开发的基类 public class ColorList extends Canvas {Vector colors = new Vector(); // 用于保存我们颜色控件中的颜色值Vector colorNames = new Vector(); // 用于保存颜色控件中的颜色名字int rowSel = ; // 用于保存当前选中的行号int oldRowSel = ; // 用于保存上一次选中的行号int maxX maxY; // 用于保存列表的宽度和高度int lineHeight; // 用于设置行高int cx = ; // 滚动条滚动后 控件的图形相对于控件可见区域左上角的x坐标int cy = ; // 滚动条滚动后 控件的图形相对于控件可见区域左上角的y坐标}控件开发最重要的就是控件的绘制了 控件的绘制可以通过添加PaintListener 在它的paintControl方法中进行 addPaintListener(new PaintListener() {public void paintControl(PaintEvent e) {GC gc = e gc;Point size = getSize();int beginx = e x;int beginy = (e y / lineHeight) lineHeight;int beginLine = (e y cy) / lineHeight;int endLine = beginLine + e height / lineHeight + ;if (endLine > getItemCount())endLine = getItemCount();for (int i = beginLine; i < endLine; i++) {boolean selected = false;if (i == rowSel)selected = true;onPaint(gc i cx beginy + (i beginLine) lineHeight selected);}}});这里要注意的是从PaintEvent中获取的x y height width是需要重绘的区域 x y是以控件的左上角为原点的坐标 在我们的程序中 为了性能起见 我们先根据需要重绘的区域计算出需要重绘的行数 只重绘相应的行 而不是将整个控件重绘 我们程序中用到的onPaint用于绘制一行 接下来 我们要让我们的控件响应键盘上下键对列表项进行选择 我们已对向上键的处理为例 首先当用户按了向上键时 我们需要改变选择 并且重绘旧的和新的选择项 如果选择项已经到了列表的顶部 我们还需要同时滚动滚动条 addListener(SWT KeyDown new Listener() {public void handleEvent(Event event) {switch (event keyCode) {case SWT ARROW_UP: // 处理向上键if (rowSel != ) {oldRowSel = rowSel;rowSel ;if (oldRowSel != rowSel) { //发送消息让控件重绘((Canvas) event widget) redraw(cx (rowSel + cy/ lineHeight) lineHeight maxX lineHeight false);}if (rowSel < cy / lineHeight) { //如果需要 滚动滚动条ScrollBar bar = ((Canvas) event widget) getVerticalBar();bar setSelection(bar getSelection() lineHeight);scrollVertical(bar);}selectionChanged(); // 发送selectionChanged事件}break;case SWT ARROW_DOWN: // down arror key…break;}}});接下来 我们要让我们的控件响应鼠标对列表项进行选择 首先我们要计算出鼠标选中的行号 注意MouseEvent中的y值只是相对于控件左上角的坐标 我们需要加上滚动出了控件的部分 addMouseListener(new MouseListener() {public void mouseDoubleClick(MouseEvent e) {}public void mouseDown(MouseEvent e) {int row = (e y cy) / lineHeight; //计算选中的行if (row >= ) {oldRowSel = rowSel;rowSel = row;}if (oldRowSel != rowSel) { // 重画旧的和新的选择项((Canvas) e getSource()) redraw(cx (e y / lineHeight) lineHeight maxX lineHeight false);((Canvas) e getSource()) redraw(cx (oldRowSel + cy/ lineHeight) lineHeight maxX lineHeight false);}selectionChanged();}public void mouseUp(MouseEvent e) {}});当我们的控件获得焦点时 选中的列表项需要有虚框表示控件得到焦点 当获得或失去焦点是 我们这里只需要简单的通知选中的项重画 addFocusListener(new FocusListener() {public void focusGained(FocusEvent e) {((Canvas) e getSource()) redraw(cx rowSel lineHeight maxX lineHeight true);}public void focusLost(FocusEvent e) {((Canvas) e getSource()) redraw(cx rowSel lineHeight maxX lineHeight true);}});我们在绘制每一个列表项时可以加入判断当前控件是否得到焦点 如果控件得到了焦点 我们就在选中的项目上画一个虚框 下面是我们绘制一个列表项的代码 注意在代码的最后绘制焦点的虚框 void onPaint(GC gc int row int beginx int beginy boolean isSelected) {Color initColor = gc getBackground();Color initForeColor = gc getForeground();if (isSelected) {gc setBackground(Display getCurrent() getSystemColor(SWT COLOR_LIST_SELECTION));gc fillRectangle(beginx beginy maxX lineHeight);gc setForeground(Display getCurrent() getSystemColor(SWT COLOR_LIST_SELECTION_TEXT));} else {gc setBackground(initColor);}gc drawString((String) colorNames get(row) beginx + beginy);Color color = Display getCurrent() getSystemColor(((Integer) colors get(row)) intValue());gc setBackground(color);gc fillRectangle(beginx + beginy + lineHeight );gc setBackground(initColor);gc setForeground(initForeColor);if (isFocusControl() && isSelected)gc drawFocus(cx beginy maxX lineHeight);}作为一个可 *** 作的控件 TAB键的支持也是很重要的 由于我们的控件是从Canvas继承过来的 不支持TAB键 下面的代码使我们的控件有TAB键的支持 addTraverseListener(new TraverseListener() {public void keyTraversed(TraverseEvent e) {if (e detail == SWT TRAVERSE_TAB_NEXT|| e detail == SWT TRAVERSE_TAB_PREVIOUS) {e doit = true;}};}); lishixinzhi/Article/program/Java/ky/201311/28014
Java对于服务器 个人电脑和移动设备来说是一项伟大的技术 由于需要java的跨平台的特性 因此java在服务器和移动设备方面的应用是非常成功的 但java在个人电脑应用方面的情况和在服务器及移动设备方面的应用有所不同 但是这很快就会有所改变 至少比你想象得要快 在这篇文章中 我会分析一下java在桌面环境中的应用将怎样得到提升 然后具体说一下java GUI(用户图形接口)的三个主要的工具:AWT Swing 和SWT 在下文中 我将会开发一个完整的java桌面应用程序 Java与桌面端 现在 流行的桌面平台要数Windows Mac and Linux了 但它们不是十全十美的 Windows主宰著桌面 *** 作系统的市场 其上有巨大的应用和开发群体 但它昂贵且有许多安全漏洞 Linux有着稳固的基础 它是开源的软件 比Windows更可靠 Macs非常容易 *** 作且不是黑客的目标 但与Windows和Linux比起来 Mac的硬件和软件可选的余地非常的有限 公司和个人选择他们的 *** 作系统基于许多因素 花费少且安全性高是首选的因素 这导致一些组织从Windows 系统转而选择Linux 对许多用户来说 可用性及对原有应用程序的支持是非常重要的因素 这意味着Windows 将继续享有巨大的市场 Mac有其自己忠诚的用户 这使得苹果机仍然可以存活 Linux 在桌面的流行及Mac的成功创造了多样性 这种多样性正是Java需要的 这种多样性使得Java在桌面有举足轻重的地位 跨平台的支持 Java 运行于所有相关的 *** 作系统 包括Windows Mac和Linux 对于任何组织 他想把现有的应用从一个 *** 作系统移植到另一个 *** 作系统而不用做太多的改动 那么Java正是他们首选的桌面开发平台 或许用微软的可视化工具很容易构建 NET应用 但是这将使你被绑定在了Windows平台上了 很多人也许想立刻用Linux 代替Windows 从而避免由微软件 *** 作系统的漏洞带来的问题 用户不能容忍的问题之一是当从Windows移植到Linux带来的巨大的费用 如果你的应用程序用Java构建 你就没有了这些问题 Java的图形用户界面看上去会跟你用的 *** 作系统一样 而并不需要做什么改动 假如有一天又有一种桌面 *** 作系统出现的话 java 是个安全的赌注 因为它现在能够运行在Windows和Linux 上 那么可以推测它也可以运行在将来可能出现的 *** 作系统上 这些 *** 作系统可能或迟或早地由微软 或是开源社区 或是其它的人开发出来 丰富的特征 最初 Java只有非常有限的一些特征去构建图形用户界面 思想就是用平台无关的Java应用程序接口打包不同的 *** 作系统的本地图形用户界面 称之为抽象的窗口工具 仅有普通的部件如文件域 文本区 选择框 单选按钮 列表框和按钮被AWT支持 图形和图像的特性支持非常有限 也就是说 只足够构建简单的applet程序 认识到需要更高级的图形用户界面组件和图形能力 Sun公司开发了Swing Java D Java D 图像的输入/输出 Java高级图像(JAI)和很多其它的 这些中的一些窗体组件现在已经是Java 标准版(J SE)里的一部分 并且其它的一些扩展必须和你的应用程序打包在一起 例如Swing Java D 图像的输入/输出都是Java的核心API 随着Java开发工具包(JDK)和Java运行环境一起提供 让我们不要忘了J EE平台 如果你开发服务器端的应用程序并且需要丰富的图形用户界面 那么你毫无疑问应该选择Java 这允许你把服务器端的一些代码移到客户端 反之亦然 例如 一个项目可能开始是基于WEB和图形界面 在某些时候 用户可能要求图形元素不能在HTML中实现 如果你选择java做客户端应用 那么你可以重用这些当初用来做服务器端的代码 如果你用远程调用 一些类会真正地实现服务器和客户端的共享 通过页面服务器 Java桌面应用也能够和其它的Java 或非Java应用程序通信 如CORBA TCP/IP 或是 >
以上就是关于Eclipse中用SWT和JFace开发入门全部的内容,包括:Eclipse中用SWT和JFace开发入门、在问你个SWT插件的问题,我想在table表格的一个格当中添加多个图标按钮,怎么添加呢、OCR技术浅析等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)