SWT:实现自我绘制的Button组件[Java编程]
本文“SWT:实现自我绘制的Button组件[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
在全部SWT组件中,Button几近是最常用的,其功效在关于普通的情形来说也充足丰富了.你可认为Button组件设置要显示在此中的文本大概图象、设定ToolTip,乃至只要改正一个气势款式就可以得到一个看上去相当不错的方向箭头按钮.
但是,我对Button组件还是不能感到称心.最大的遗憾就是:对它的外观,所能做的工作也就仅限于此了.假如你想让按钮拥有一个漂亮的、突变色的后台和一些特别的文字效果,怎么办呢?答案是没有办法.Button类里面仿佛没有任何办法供应我想要的功效.
我曾尝试过的第一个设法是用Button.addPaintListener来改正按钮的外观.但是,后果令人绝望——固然它显示出来的时刻的确按照预想举行绘制了,但是当你用鼠标去按它的时刻,即刻又变回了本来灰头土脸的模样.明显,在按下按钮的时刻,它并非触发paint事件,而是按照自己的设法画出本来的按钮,于是我的工作全部白费了.
假如尝试为按钮设定图象会怎么样呢?这也不是一个好主张.首先,不管你挑选什么样的图象,都没办法去掉按钮四周的边框,而恰是这些边框严重破坏了图象的和谐感;其次,假如你的程序有几十乃至上百个按钮,为每个按钮都保护一幅图象(乃至更多——理论上每个按钮在普通状况和被按下、禁用的状况下,乃至当鼠标移进移出按钮的时刻,都该当显示差别的图象)明显是在浪费系统资源;假如你们的美工据说需求做几百个图片,大约也不会给你好表情看.此外,图象有一个严重的缺陷是:它所拥有的像素数目是固定的,难以随着界面的放大和缩小同时改变.假如强迫举行缩放的话,会呈现明显的锯齿和失真,终究让你尽心计划的窗口变得惨无人性.最好还是放弃这个设法.
假如以Canvas为底子,计划一个假装的按钮组件又若何呢?听起来仿佛很不错,因为采取这种办法的话,我们对若何绘制组件的表面就有了完好的掌握权.不过这也意味着你必须对按钮的状况举行手工保护.固然Button本身是一个很简单的组件,但是反复去做尺度按钮已经作好的工作仿佛还是有点无谓.还有一件事情是该当考虑的:我们知道,JFace中的Action机制可以将尺度按钮、菜单项和工具栏按钮这三种界面组件归入一个统一的事件处理体系.但是,假如我们从Canvas派生去模拟一个按钮的话,不管你模拟到多么类似的地步,它毕竟不是一个真正的Button,Action也不会给它平等的报酬.也就是说手工制作的按钮无法和JFace Action体系协同工作——除非你去改正Action的处理办法,让它去采取新的按钮对象.这可不是一件轻松的工作.
假如上面的办法都行不通的话,该当怎么办呢?我们知道,和Swing这样的框架差别,SWT中的按钮其实就是操作系统底层所实现的按钮(这一点也可以用SPY++大概Winsight32之类的工具证实).同时我们也知道,操作系统——至少是Windows系统,对按钮已经供应了自我绘制的机制,这就是所谓的Owner Draw(称为全部者绘制的缘由是因为默许情形下绘制消息是发送给按钮的父窗口处理的,但是父窗口也可以把这个皮球再踢回给按钮,让它自己办理).在Win32 API中,但凡利用BS_OWNERDRAW气势成立、并且可以(通过消息反射)呼应WS_DRAWITEM消息的按钮,都可以得到这种定制的本领. 理解这一点,接下来的任务就是研究Button组件有没有开放这个接供词我们改正了.对Button组件的源代码举行大概的浏览后,我发现了以下的办法:
package org.eclipse.swt.widgets;
public class Button extends Control {
…
LRESULT wmDrawChild (int wParam, int lParam) {
if ((style & SWT.ARROW) == 0) return super.wmDrawChild (wParam, lParam);
DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
....
此中DRAWITEMSTRUCT构造的呈现是一个明显的提醒:这里就是WM_DRAWITEM消息的呼应函数,很幸运它没有声明为final的,只要重载它并供应自己的实现就行了.
看起来是个小case,实际上也是.不过,还有一处小麻烦需求降服.注意wmDrawChild办法没有利用任何拜候限定符,这意味着它是package friendly的——同一个包中的对象可以拜候和重载此办法,其他包中的对象就没有这个权利了.也就是说,要定制按钮对象,我们新建的对象也需求放在同一个包(org.eclipse.swt.widgets)中.看起来有点像在利用Hack手段,不过为了冲破SWT给我们的限制,眼下也只好稍稍将就一下.好在swt的包没有密封(Sealed),不然我就不得不再次声称此路不通了.
既然障碍已经扫清,接下来我们可以来实现前面的设法了.这里我做了一个决意,在上述包中只加入一个抽象类,目的是把必要的接口表暴露来;至于若何绘制按钮,则留给具体的按钮对象按照利用程序的需求来决意.这样,不管你但愿实现Windows XP气势的按钮、还是卡通气势的按钮、或是平面款式的,总之不管什么千奇百怪的气势,只要担当一个类并重载一个绘制办法就行了,而没必要每次都要和 Button类的内部打交道.
基于这种考虑,实现自绘按钮的抽象类以下:
package org.eclipse.swt.widgets;
import org.eclipse.swt.internal.win32.*;
public abstract class OwnerDrawButton extends Button
{
public OwnerDrawButton( Composite parent, int style )
{
super( parent, style );
int osStyle = OS.GetWindowLong( handle, OS.GWL_STYLE );
osStyle |= OS.BS_OWNERDRAW;
OS.SetWindowLong( handle, OS.GWL_STYLE, osStyle );
}
LRESULT wmDrawChild( int wParam, int lParam )
{
super.wmDrawChild( wParam, lParam );
DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT();
OS.MoveMemory( struct, lParam, DRAWITEMSTRUCT.sizeof );
ownerDraw( struct );
return null;
}
protected abstract void ownerDraw( DRAWITEMSTRUCT dis );
}
以上是“SWT:实现自我绘制的Button组件[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |