SWT/JFace入门指南之让SWT措施动起来
副标题#e#
我不知道各人有没有这样的体验:其实软件利用者要求的对象都很根基,而此刻软件做得越来越巨大,有相当大一部门是在于软件开拓者把本身的留意力放在了一些附加成果(这些成果大概让用户感想惊喜,可是假如没有它们用户也不会不满足)上,而真正用户的要求却得不到满意。所以各人在设计措施的时候,必然要大白,有时候简朴就是一种美,把时间耗费到真正有代价的处所去。
OK,回到我们的主题上来。在这一节中,我将给各人先容swt的事件模式。在前面我们也提到过,写一个swt措施,无非就是分几步走。个中较量需要操心的就是部署好用户界面和处理惩罚各类事件。
添加了事件处理惩罚的Hello,world!
其实swt中处理惩罚事件很是简朴,对应于各类事件都有相应的listener类,假如一种事件叫做Xyz,那么对应的listener类就是XyzListener。好比对应于鼠标事件的有MouseListener,对应于键盘事件的就是KeyListener。而在每种widget中,对付它可以处理惩罚的事件都有addXyzListener要领,只要把对应的listener实例作为参数传给它就可以了。
为了越发清楚的说明,我们先来看下面一段措施:
1 public class EventDemo {
2
3 private Shell _shell;
4
5 public EventDemo() {
6 Display display = new Display();
7 Shell shell = new Shell(display,SWT.SHELL_TRIM);
8 setShell(shell);
9 RowLayout layout=new RowLayout();
10 shell.setLayout(layout);
11 shell.setText("Event demo");
12
13 Button button=new Button(shell,SWT.PUSH | SWT.CENTER);
14 button.setText("Click me!");
15
16 button.addSelectionListener(new SelectionListener(){
17
18 public void widgetSelected(SelectionEvent event) {
19 handleSelectionEvent();
20 }
21
22 public void widgetDefaultSelected(SelectionEvent event) {
23 }
24 });
25 shell.setBounds(200,300,100,100);
26 shell.open();
27
28 while (!shell.isDisposed()) {
29 if (!display.readAndDispatch()) {
30 display.sleep();
31 }
32 }
33 display.dispose();
34
35 }
36
37 protected void handleSelectionEvent() {
38 MessageBox dialog=new MessageBox(getShell(),SWT.OK|SWT.ICON_INFORMATION);
39 dialog.setText("Hello");
40 dialog.setMessage("Hello,world!");
41 dialog.open();
42 }
43
44 /**
45 * @param args
46 */
47 public static void main(String[] args) {
48
49 EventDemo eventdemo=new EventDemo();
50 }
51
52 /**
53 * @return Returns the _shell.
54 */
55 public Shell getShell() {
56 return _shell;
57 }
58
59 /**
60 * @param _shell The _shell to set.
61 */
62 public void setShell(Shell shell) {
63 this._shell =shell;
64 }
65 }
66
#p#副标题#e#
代码段 6
你可以看到在这段措施中,我们只建设了一个Button,随后挪用了它的addSelectionListener()要领,在这个新建设的Listener,我们只为widgetSelected要领添加了代码,并在个中建设了一个对话框。
假如总结一下,我们可以得出处理惩罚事件的几个步调:
1.针对你所处理惩罚的事件,找出符合的XyzListener接口
2.编写一个新的类,这个类实现了XyzListener接口
3.在你所感乐趣的事件中编写处理惩罚代码,而对付那些你不感乐趣的要领可以让它们保持空缺(就像实例中的widgetDefaultSelected()要领)一样
让事件处理惩罚越发简朴:利用适配器(adapter)
有时候我们大概会感受这样仍然不足简朴,好比我只对SelectionListener中的widgetSelected()要领感乐趣,可是为了可以或许通过编译器的编译,我却不得不写一个空缺的widgetDefaultSelected()要领(因为SelectionListener是一个接口,你必需实现它所有的要领)。
幸运的是,swt帮我们办理了这个问题,途径就是利用adapter。在swt中,对应于一个XyzListener都有一个XyzAdapter,adapter都是抽象类而且实现了对应的listener接口,它为对应listener接口中的每个要领都界说了一个默认实现(根基上就是什么都不做),我们在利用时候只需要override掉本身感乐趣的要领就可以了。
团结上一小节中的代码,假如利用SelectionAdapter取代SelectionListener的话,我们的代码就可以这样写:
button.addSelectionListener(new SelectionAdapter(){
public void widgetSelected(SelectionEvent event) {
handleSelectionEvent();
}
});
这样是不是很利便呢?
EventObject:事件处理惩罚的附加信息
在处理惩罚各类事件时,我们需要一些附加信息,而EventObject给我们提供了这些信息。
我们先来看下面这个简朴的小措施,在这段措施中,我们建设了两个文本框,当在第一个文本框输入时,第二个文本框中显示输入的字符。
#p#分页标题#e#
1 public class EventDemo2 {
2
3 Text logText;
4
5 public EventDemo2() {
6 Display display = new Display();
7 Shell shell = new Shell(display,SWT.SHELL_TRIM);
8
9 GridLayout layout=new GridLayout();
10 layout.numColumns=2;
11 shell.setLayout(layout);
12 shell.setText("Event demo");
13
14 Label label1=new Label(shell,SWT.RIGHT);
15 label1.setText("text1:");
16 Text text1=new Text(shell,SWT.NONE);
17
18 text1.addKeyListener(new KeyAdapter(){
19 public void keyPressed(KeyEvent e) {
20 Text t=getLogText();
21 String s=t.getText();
22 t.setText(String.valueOf(e.character));
23 }
24 }
25 );
26
27 Label label2=new Label(shell,SWT.RIGHT);
28 label2.setText("text2:");
29 Text text2=new Text(shell,SWT.NONE);
30 text2.setEditable(false);
31 text2.setBackground(new Color(display,255,255,255));
32 setLogText(text2);
33
34 shell.pack();
35 shell.open();
36
37 while (!shell.isDisposed()) {
38 if (!display.readAndDispatch()) {
39 display.sleep();
40 }
41 }
42 display.dispose();
43 }
44 /**
45 * @param args
46 */
47 public static void main(String[] args) {
48 EventDemo2 demo2=new EventDemo2();
49 }
50 /**
51 * @return Returns the logText.
52 */
53 public Text getLogText() {
54 return logText;
55 }
56 /**
57 * @param logText The logText to set.
58 */
59 public void setLogText(Text logText) {
60 this.logText = logText;
61 }
62 }
63
代码段 7
你大概没有乐趣仔细研究这么长的代码,那么让我们只存眷这一小段代码:
text1.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e) {
Text t=getLogText();
String s=t.getText();
t.setText(String.valueOf(e.character));
}
}
);
在这段代码中,我们利用了KeyAdapter来处理惩罚键盘事件,而keyPressed会在有键按下时候被挪用,我们在函数中利用了KeyEvent范例的参数e,而且通过e.character获得了按下键对应的字符。
各类EventObject(譬喻上面示例中的KeyEvent)在事件处理惩罚函数中作为参数呈现,它们大概有差异的属性和要领,操作这些特性我们可以做许多有意思的工作。
我们下面只简朴先容几种EventObject,它们别离是对应于窗口事件(ShellListener,ShellAdapter)的ShellEvent,对应于键盘事件(KeyListener,KeyAdapter)的KeyEvent和对应于鼠标事件(MouseListener,MouseAdapter)的MouseEvent。但愿可以起到窥一斑而见全豹的浸染。
几种EventObject简介
ShellEvent
假如你打开ShellEvent的API,你会很惊奇的发明它只有一个布尔型的属性,就是doit。这个莫名其妙的属性是用来做什么的呢?
我们知道,Shell对应的就是措施的窗口,在ShellListener中界说的几种事件包罗窗口激活时候的shellActivated,窗口即将被封锁时候的shellClosed等等。ShellEvent中独一的属性doit,就是用来设定是否这些行动将有效的。
再说得详细一些,好比Windows下凡是我们会通过点击窗口右上角的封锁按钮来封锁窗口,这个时候就会对shellClosed举办挪用,假如我们在shellClosed(ShellEvent e)要领中把ShellEvent工具e的doit属性置为了false,那么这次行动就无效,窗口不会被封锁。
在有些其他的EventObject中也有doit属性,它们的浸染都是雷同的。好比KeyEvent就有这样的一个属性。假如你在keyPressed要领中把它置为了false,就便是你按键盘(对付对应的widget,也就是receiver来讲)没有用。
KeyEvent
其实在前面我们或多或少的已经先容了一些KeyEvent的常识。KeyEvent包括四个属性:character,doit,keyCode和stateMask。
个中character我们在前面的示例中利用过,它其实就是按键对应字符,而doit和ShellEvent中的doit寄义是沟通的。
keyCode是我们称为键码的对象,什么是键码呢?假如你打开org.eclipse.swt.SWT的API文档,你会发明内里有许多都和键盘有关的整型常量,好比SWT.F1,SWT.F4,SWT.ESC,SWT.KEYPAD_3之类,这就是他们的键码。
而stateMask则是用来检测Alt,Shift,Ctrl这些键有没有同时被按下。
用stateMask与这些键的键码举办位与运算,假如获得的功效不是0就说明这些键被按下了,好比假如stateMake & SWT.ALT不为零,我们就可以认为Alt键被按下了。
MouseEvent
MouseEvent对应于的是鼠标事件。它同样包括四个属性:button,stateMask,x,y
button就是说明按下的是哪个键,好比对付普通鼠标来说,1是左键,2是右键等等
stateMask却是用来反应键盘的状态的,这和KeyEvent中的stateMask寄义是沟通的。
x和y指的是相对付部件的横坐标和纵坐标。
#p#分页标题#e#
你大概会以为有点疑问,光是这么一点属性就能处理惩罚鼠标事件了么?假如我有一个滚轮鼠标,那应该用什么事件处理惩罚滚轮的行动呢?谜底是:今朝大概还无法操作事件模式处理惩罚,关于这一点可以参照一下这个url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=58656
关于EventObject我就只先容到这里,这虽然很不足,可是我强烈发起各人在实际应用中多查阅eclipse和swt的相关文档。因为究竟精神有限,我的目标是让各人通过这篇文章可以或许找到一个正确获取常识的偏向,而不是把这些常识很具体的先容给各人。
Untyped Events
我们在这里提到了untyped events,那必定就有typed event,typed和untyped自己并不是说事件有什么纷歧样,而是说事件处理惩罚是利用了特定的Listener照旧没有。我们前面提到的所有事件处理惩罚都是typed 范例,因为它们都利用了特定Listener。
所谓的untyped events你可以领略为一个事件的大杂烩。和untyped event相接洽的两个类是Listener和Event。在这里我想请各人留意一下,这两个类不是在org.eclipse.swt.events中,而是在org.eclipse.swt.widgets中。
Listener只有一个要领handleEvent,这个要领里你可以处理惩罚任何事件。而假如你打开Event看一下,就能看到我们方才在前一小节中先容过的那些XxxEvent中的属性在这里包罗万象。所以它可以起到替代它们的浸染,虽然假如是一个窗口被封锁的事件,相信你用keyCode属性意义不大。
让我们看一下下面一段代码
1 Shell shell = new Shell ();
2 Listener listener = new Listener () {
3 public void handleEvent (Event e) {
4 switch (e.type) {
5 case SWT.Resize:
6 System.out.println ("Resize received");
7 break;
8 case SWT.Paint:
9 System.out.println ("Paint received");
10 break;
11 default:
12 System.out.println ("Unknown event received");
13 }
14 }
15 };
16 shell.addListener (SWT.Resize, listener);
17 shell.addListener (SWT.Paint, listener);
18
代码段 8
由此我们概略上可以体会到untyped events的处理惩罚方法。
小结
关于事件处理惩罚,我就向各人先容这么多。到此刻为止,我们已经根基上可以写一些简朴的swt用户交互措施了。然而这还远远不足,究竟人们老是但愿有更富丽(可能说:富厚)的界面,让用户可以或许得到更好的体验。在下一节中,我打算和各人接头一些这样的部件。
别的大概你以为有些迷惑,为什么写了这么多内容,都是关于swt的呢?Jface的内容呢?我的打算是在大部门swt有关的内容先容完了今后再向各人先容Jface。事实上,纵然不消Jface,你也完全可以用swt构筑起一个很是完美的措施来。