Tips_GUI&事件编程

http://spaces.msn.com/seman/Blog/cns!1pUoDdawYMrLWuL3Hn9GWolQ!280.entry
事件是一种形式化的软件模式,在该模式中,通知源将对一个或多个处理程 序方法进行回调。因此,事件类似于接口和委托,因为它们提供了设计使用回调方法的应用程序的方法。但是,事件极大地提高了工作效率,因为它们使用起来比接 口或委托更容易。 事件允许编译器和 Visual Studio® .NET IDE 在幕后为您做大量的工作。
涉及事件的设计基于事件源和一个或多个事件处理程序。 事件源可以是一个类也可以是一个对象。 事件处理程序是绑定到处理程序方法的委托对象。

 

www.vckbase.com/document/viewdoc/?id=1616
事件事件编程。它是个重要的主题,当今对事件 没有坚实的理解,你是无法编写程序的—— ... 如果过程化编程是自顶向下的,事件编程是 自底向上。

 

http://www-128.ibm.com/developerworks/cn/linux/l-perlgtk/#N10155
基本概念

  
  
  
  我们开始介绍一些在 Gtk2-perl 编程中一定要理解的基本概念。有了对这些概念的理解,你才可以轻易的进行更深入的学习。
这些概念并不仅仅适用于 Gtk2-perl 的编程,很多概念也适用于大多数的 gui 编程

1) 事件驱动模型

事件驱动模型可以算作是 GUI 编程中最为重要的概念之一了。平时,我们运行的一般程序都是采用典型的批量处理模式以线性的方式运行所有的命令。然而,一个交互式的用户界面程序必须随时 准备运行任何一个操作:一个用户可能正漫步于菜单上,然后按下任何他想要的按钮,或者用户正在一个文字输入栏输入文字,或者他忽然切换到其他程序然后又再 切换回来完成刚才他没做完的事情。总之,程序必须随时响应用户触发的事件,这就叫做"事件驱动"。可以说,如果没有事件驱动模型,我们就无法实现用户的自 由操作,不理解事件驱动模型,我们就无法开始 Gtk2-perl 的编程。

事件驱动模型一般有这样的特点:

  • 归纳出基本的元素,例如:对于用户所有可能的动作事先要做出归纳总结。
  • 一个事件驱动程序一般都有一个处于中心地位的事件队列处理部分和一个事件队列。当一个事件发生时就向事件队列添加一项。事件队列处理部分则不断地处理事件队列中的各种事件,而且每处理一个事件时都要通知对这个事件感兴趣的子程序。

我们来更加具体的解释一下:当用户点击一个按钮的时候,一个按钮事件就被添加到事件队列中,随着事件队列的不断被处理,轮到我们添加的按钮事件时,事件队列处理部分就会开始处理这个事件,同时通知任何对这个事件感兴趣的子程序。

在 Gtk2-perl 中,事件驱动的逻辑实现是在内部完成的。我们只需要理解这个概念就可以了。

2) 主循环系统

所谓的主循环系统就是上面我们介绍的事件队列处理系统的一部分。由于我们需要无限的等待用户的输入事件,所以我们必须建立一个循环,这个循环可以不 断的读出用户的输入事件,并处理这些事件,在这个循环中我们还要处理一些其他的事情,例如等待 socket 数据到来等等,这就是主循环系统。主循环系统有时要处理事件,但是在大多数时候,主循环一般会处于空闲状态。在空闲状态下,主循环系统释放 cpu 等计算机资源,等待新的事件到来。一个好的 GUI 系统,空闲时间的分配是十分重要的。为了随时能够响应用户的输入,必须有足够的空闲等待用户的输入。如果大量的资源都被占用,那么用户的输入将得不到及时 地响应,用户对于这个 GUI 系统将会十分失望。

在 Gtk2-perl 中,Gtk2 -> main 语句代表着开始主循环。

顺便一提:Gtk2 -> init 语句代表 Gtk2-perl 程序的初始化,在任何 Gtk2-perl 程序中,我们都必须先初始化,初始化完成后我们才可以开始编写与 Gtk+ 相关的语句。

3) 信号系统

信号系统也是事件驱动模型中的一部分。所谓信号系统就是当某一件事情(例如,用户的某个操作动作)发生的时候我们就会得到一个信号,然后我们按照事先规定好的如何处理这种信号的方法来处理这个信号。

在 Gtk2-perl 中,我们的信号系统有两种,一种是底层的通用信号系统,一种是每个控件特殊的信号系统。

底层的通用信号都有自己的唯一独立名称,总共有 30 多种。这些信号一般是用在自定义的控件中,例如:现有的控件没有能达到你的需要,你想自己的编写一个特殊目的的控件,这时要用到的信号系统就是底层的通用信号。

每个控件的独立信号系统,随着控件的不同而不同,例如:按钮 button 控件可以有自己的信号系统,当 'pressed' 信号发生时证明用户正在按下这个按钮;而文字 textview 控件也有自己的信号系统,当我们在文字控件中移动光标时,我们就可以触发 move-cursor 信号。 信号系统的基本原则是必须明确声明信号才能生效。换句话说就是如果对于某个信号你没有事先声明要捕获这个信号,那么系统将不会理会这个信号。即使是最简单 的关闭窗口信号,如果没有事先声明,系统也不会理会,就像我们上面的 Helloworld.pl 中的一定要添加 $win -> signal_connect ( destroy => sub {Gtk2 -> main_quit } );这句话,否则点击关闭窗口的按钮将不起作用。这一点对于最初接触 GUI 编程的朋友一定要注意。 信号系统的一般用法是:$widget -> signal_connect ('signal' , sub{do…} );这里 $widget 一般是指 GUI 程序中的某个窗体,在这里我们看到,我们在某个$widget 上添加信号捕获,当某个 signal 发生时,我们就去执行 sub{ do…. } 的子程序。

4) 绘图上下文

所谓的绘图上下文就是用来封装绘图属性的,所有的绘图操作都要用绘图上下文来作为自己的参数。简单点说就是绘图上下文就是一个包含了所有的绘图属性 的对象(例如:背景的色彩,一条线的宽度等等),然后将这个绘图上下文作为你要绘制图像的参数来输入从而决定这个图像如何绘制。

绘图上下文的优势在于:通过使用绘图上下文将各种绘图属性的集中在几个对象,可以大大的减少重复的绘图属性的设定,从而让一个绘图上下文为多个不同的绘图来作为参数。更加准确的说,这种优势是为了减少程序中的重复编写与输入,提高程序的编写与运行效率

绘图上下文的基本用法:$gc = Gtk2::Gdk::GC -> new ( $drawable , $values=undef )

5) Gtk2-perl 的内部控件

现代 GUI 编程的一个特点就是提供大量的易用控件给开发者,每个控件都可以完成某个特定的功能(例如:显示一段文字或允许用户输入一段文字等等),这样使得开发者在 开发一个 GUI 程序时可以用这些控件来组装成一个 GUI 程序。这很类似于我们现在的 html 格式的 web 制作,在我们制作一个网页时,就是利用了很多现成的 html 标签然后组合到一起形成完整的 html 网页。这种相似性甚至可以在很多微小的方面得到验证,例如将这些控件正确的布局时都要用到表格这样的控件。

在 Gtk2-perl 中提供的控件相当丰富,我们单单来看看这些控件的大类:

Windows:这个控件大类是负责最基本的 GUI 窗口,例如:主窗体控件,简单对话框的控件。

Display Widgets:这个控件类是负责基本显示的,例如:文字显示控件,图片显示控件。

Buttons and Toggles:负责各种类型的按钮,如基本按钮,check 类型的,radio 类型的。

Numeric/Text Data Entry:负责数字与文字的单行输入。

Multiline Text Editor:负责文字多行输入的控件。

Tree, List and Icon Grid Widgets:负责树形列表式、简单列表式或图标表格式的显示。

Menus, Combo Box, Toolbar:负责菜单、组合单元、工具栏。

Action-based menus and toolbars:负责基于动作的菜单与工具栏

Selectors (File/Font/Color/Input Devices) :负责文件、字体、颜色、输入设备的选择界面,这就是我们在打开文件或选择字体时所使用的那个通用的界面。

Layout Containers:负责各个控件的布局,让你可以很容易的在一个窗口上布置各个空间。

Ornaments:负责控件显示时的周围装饰,例如在各个控件间的分割条等

Scrolling:负责滚动条,用来将一些无法用一屏显示的控件中的内容滚动的显示。

Miscellaneous:负责其他剩余的事情,如显示一个箭头的控件,日历控件,一个绘画区域的控件等等。

Abstract Base Classes:负责抽象的控件,这些控件一般是基本控件的父类。

Cross-process Embedding:负责两个进程间的通讯。

Special-purpose features:负责某些特殊目的,例如:绘制曲线的控件,绘制标尺的控件。

所有的这些控件他们一般都有面向对象的特征,也就是存在父类与子类。父类一般是几个相似控件的一个集合。每个子类都可以使用父类的函数。这样使我们使用起这些控件更为方便,这也是 Gtk2-perl 的一个优势吧。

我们只是讲述了一下 Gtk2-perl 编程的一些基本信息,掌握这些基本信息对于任何 Gtk2-perl 的初学者而言都是十分重要的。在这些基础之上,大家可以参照 Gtk2-perl 源代码中附带的例子尝试性的开始编写某些小的 Gtk2-perl 程序。对于在编写过程中遇到的问题,大家可以参考 Gtk2-perl 的主页上的英文文档


能力与优势

1.首先 Gtk2-perl 是跨平台的。Gtk2-perl的跨平台能力来自于 Gtk+ 本身是一个跨多平台的工具包,而 Perl 也是跨平台的语言
Gtk2-perl 的这种跨平台能力在 Gui 开发工具中并不多见,同样著名的跨平台开发工具还有 Qt,一个 C++ 的 Gui 开发工具包,其功能也十分强大,不过 Qt 对于其他语言的移植很差。SDL,一个 C 的多媒体开发工具包, 不过 SDL 偏重于游戏的开发,在 SDL 内并没有提供窗体的支持,也就是说你无法调用现成的 api 来生成默认 windows 风格的程序。其他较著名的 Gui 开发工具包还有微软的 GDI+,由于是私有公司开发的原因,GDI+ 开发的程序是只能在 win32 平台下运行。(还有 directx 和 opengl,这两者都是 3D 图形的开发工具包,现在还大多用于游戏的开发,普通应用程序并不使用它们)。

2.其次,Gtk2-perl 的程序可以基本不用改动便可在多个平台运行。这对于程序员来说意味着写一遍程序,就可以顾及到所有的流行平台,这大大降低了程序员的后续工作量,提高了程 序的生命力。Gtk2-perl 程序由于是 perl 脚本,甚至省去了在这些平台的编译工作,相对于 Qt 编写的程序还要在各个平台再进行重新编译,在编译过程中还可能出现某些由于平台的差异而产生的编译问题(这里有朋友可能要说我不想暴露源码,那你可以试试 perl 的某些包装源码的模块比如 par,但是笔者认为即使从经济角度出发这样做的意义也不大)。只要你在编写 Gtk2-perl 程序前注意到某些平台的不同之处,对于某些特殊的应用有专门的代码处理就可以很方便的实现跨平台的能力,例如,在 X11 下使用与 X11 相关的调用,这时就要指明只有在 Xserver 存在时才能这么用。

3.用 Gtk2-perl 编写 Gui 程序可以不必关心内存的分配情况,而将自己的主要精力放在程序的实现上。这样的能力来源于 Perl。由于 Perl 语言先天的特性,它为你管理好了内存,所以你不必在意这些。

6.Gtk2-perl 采用了 gui 编程中的先进思想。例如:事件驱动模型,绘图上下文系统等等。这些都是从过去的 
gui编程模型中总结出来的。这些能力是由于 gtk+ 的最初设计。gtk+ 的设计理念也是综合了当今最先进的 gui 工具包的设计理念而形成的。




http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=142&threadID=5637&messageID=187072
GUI编程过去常常需要编程高手来进行,因为它需要复杂的事件驱动异步编程。后来,PowerBuilder 和 Visual Basic
提供了一个范例,使人人都可以利用 GUI 编程。WLI
(weblogic) Workshop 在集成编程方面所做的工作也是如此。
它不再需要编程高手去编写异步事件驱动



http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/vccore/html/vcconeventhandlingusingattributes.asp

Visual C++ 中的事件处理使用统一事件模型,该模型使您可以将同一编程模型用于所有类型的 Visual C++ 类中的事件处理:

  • 本机 C++ 类(不实现 COM 对象的 C++ 类)。
  • COM 类(通常使用 ATL 类或 coclass 属性实现 COM 对象的 C++ 类)。
  • 托管类(用 __gc 关键字或通过托管上下文中的声明进行声明的 C++ 类)。

统一事件模型介绍

在过去,各种编程环境已经提供了各自不同的方法,使组件将有关异步“事件”的信息传递回客户端。C 语言所具有的函数回调对此非常适用,而 C++ 却始终缺少这种针对对象方法的回调。要找到相应的方法处理 C++ 中存在的这种缺陷,可能需耗费大量时间(使用窗口消息、事件接口、硬编码回调方法名、thunk 等等)。COM 虽然定义了一个事件模型,但该模型不便于实现和管理,并且不提供两个本机 C++ 对象之间的事件支持。

统一事件模型的目的是使应用程序能够这样使用事件:使组件对其客户端的了解和依赖性最小化,而使组件的可重用性最大化,并且对于本机(非 COM)C++、COM 和托管类以一致的方式实现此目的。

该模型支持单线程和多线程的使用,并禁止对数据进行同步多线程访问。它还使您得以从事件源或接收器类派生子类,并支持此派生类中的扩展事件源/接收。

事件处理元素

“事件源”是定义事件和包含事件的对象。使用 event_source 属性创建事件源。

“事件”是事件源中的方法,该方法在被调用时生成事件。使用关键字 __event 定义事件。“引发”事件是指通过调用事件方法“激发”该事件。

“委托”是可保持对方法的引用的类。委托类不同于其他类的地方在于,该类具有签名,并且只保持对与其签名相匹配的方法的引用。.NET Framework 具有一个特定的委托模型;如果您正在开发 .NET Framework 的组件,请参见事件和委托

“事件接收器”(也称为事件接收)是接收事件的对象。使用 event_receiver 属性创建事件接收器。

“事件处理程序”是事件接收器中接收事件的方法。

“挂钩”事件是指将事件与事件处理程序相关联(即在事件处理程序中注册事件)。使用内部函数 __hook 将处理程序方法与事件相关联。

“解除挂钩”事件是指使事件与事件处理程序分离(即撤销事件的注册)。使用内部函数 __unhook 使处理程序方法与事件分离。
(发明了这么多的狗屎概念,绝对把你搞晕菜)


http://www.vckbase.com/document/viewdoc/?id=1616
大体上介绍一下事件和事件编程。它是个重要的主题,当今对事件没有坚实的理解,你是无法编写程序的——什么是事件以及什么时候使用事件。
  成功的编程完全在于对复杂性的掌控。很久以前,函数被称为“子程序”(我知道,我这样说证明我已经老了!)管理复杂性的主要方式之一是自顶向下的编程 模式。高层实现类似“宇宙模型”,然后将它划分为更小的任务如:“银河系模型”以及“太阳系模型”等等,直到任务被划分为可以用单个函数实现为止。目前自 顶向下的编程模型仍被用于过程化的任务实现当中,但它不适用于发生顺序不确定的实时事件响应系统。经典的例子便是 GUI,程序必须响应用户的某些行为,比如按键或是鼠标移动。实际上,事件编程很大程度上源于图形用户界面的出现。
  在自顶向下的模型中,在顶部的高级部分对低级的实现各种不同任务的函数——如 DoThis,DoThat 进行食物链式的调用。但不久以后,低层部分需要回调(talk back)

如果过程化编程是自顶向下的,事件编程是自底向上。在典型的软件系统中,函数的调用流是从较高级部分到低级部分进行的;而事件是以相反的方向过滤的

那么到底什么叫事件?其实,事件就是回调。而不是在编译时就已知名字的函数调用,组件调用在运行时调用你提供的函数。在 Windows 中,它是一个窗口过程。在 .NET 框架中,它叫做委托。不管术语怎么叫,事件提供了一种软件组件调用函数的方式,这种调用方式直到运行时才知道要调用什么函数。回调被称为事件处理器。发生 或触发一个事件意味调用这个事件处理器。为此,事件接收部分首先得给事件源提供一个事件处理器的指针,这个过程叫注册
  通常在以下几种场合下我们要使用事件:

  • 通知客户机实际的事件:用户按下某个按键;午夜时钟敲响;风扇停止工作造成 CPU 烧毁;
  • 当拷贝文件或搜索巨型数据库时,报告耗时操作的过程,组件可以周期性地触发某个事件以报告已拷贝了多少文件或已搜索了多少记录;
  • 如果你使用 IWebBrowser2 在自己的应用程序中宿主 IE,报告所发生的重要的或引起注意的事件,浏览器会在导航到某个新页面之前或之后通知你,或者在创建一个新窗口时通知你。
  • 调用应用程序提供的算法:C 运行时库函数 qsort 排序对象数组,但你必须提供比较函数。借助许多 STL 容器也能实现同样的诀窍.大多数程序员不会调用 qsort 回调某个事件,但你没有理由不考虑那种方式。它是“时间比较”事件。

  一些读者问:异常和事件之间有什么差别?主要差别是:异常表示不应该发生的意外情况。例如,你的程序运行耗尽内存,或者遇到被零除。这些都是你并不希 望发生的异常情况,并且一旦出现这些情况,你的程序必须要做出相应的处理。另一方面,事件则是每天常规操作的部分并且完全是预期的。用户移动鼠标或按下某 个键。浏览器导航到一个新页面。从控制流的角度看,事件是一次函数调用,而异常则是堆栈的突然跳跃,用展开的语义销毁丢失的对象。
  有关事件常见的概念误解是认为它们是异步的。虽然事件常常被用于处理用户输入和其它异步发生的行为 ,但事件本身是以同步方式发生的。触发一个事件与调用该事件处理器是同一件事情。用伪码表示就像如下的代码段:

// raise Foo event
for (/* each registered object */) {
obj->FooHandler(/* args */);
}
控制立即传到事件处理器,并且不会返回,除非处理完成。某些系统提供某种以异步触发事件的方式,例如,在 Windows 中,你可以用 PostMessage 代替 SendMessage。控制会从 PostMessage 立即返回,该消息是后来才处理的。但是 .NET 框架中的事件以及我在这里讨论的事件是在触发时被立即处理的。当然,你总是可以触发来自运行在单独的线程中的消息代码事件,或者使用异步委托调用在线程池中执行每个事件处理器,在这种情况下,相对于主线程来说,事件是异步发生的。

 



http://blog.gceclub.sun.com.cn/index.php?op=ViewArticle&articleId=254&blogId=3
观察者模式在Java编程中的应用
观察者模式 Observer Pattern )在 Java 应用程序中广泛应用。此模式属于行为设计模式。它定义了一个方法可以使得类之间松耦合,并且可以当一个类更新的时候另一个或者多个类得到通知。基本的意思是,当一个地方的某些事情发生后,你来通知其他对此事件感兴趣,正在观察着的人。

有两种方式来查看观察者设计模式的细节。第一种办法是了解定义在java.utilObserverObservable类。第二种方法是研究注册事件监听器的JavaBeans组件模型。

在创建JavaBeans事件模型之前,ObserverObservable类就描述了观察者涉及模式的实现。换句话说,自从Java平台1.0版本,这些类就已经存在了。由于这些类在设计上并没有什么技术错误,因此一直沿用下来了。这些类现在还可以用于实现观察者模式,但是用的更多的是JavaBeans事件模型。使用ObserverObservable实现观察者模式存在一个问题就是你必须要扩展Observable类,这就强迫使用这样的类结构了,因为Java平台是只允许单继承的。

事件注册监听器JavaBeans组件模型中包含了一系列的添加和删除方法,方法的名称中包含了监听器的类型。例如,想要监听按钮的选择,你需要注册ActionListener,如下:

ActionListener listener = new ActionListener() {

public void actionPerformed(ActionEvent actionEvent) {

...

}

};

JButton button = new JButton("Pick Me");

button.addActionListener(listener);

在这里,我们实现一个监听器接口,将其附加到监听的对象上。监听的对象就是被监听的。它的职责是记住谁在监听,在JavaBeans组件模型中,用于附加和解除Observer对象的接口是添加和删除监听器命名模式。当监听对象的状态改变的时候,它会通知Observer对象。

这种设计模式的一个主要目标就是将对象和观察者的耦合度降低。当JButton被选择的时候,并非调用一个叫做ButtonNotification类的特定方法,通知动作被抽象到一个接口中,任何类都可以实现它。JButton并不关心绑定的监听器是什么。事实上,按钮不关心实现类是不是被修改了。它关心的是观察者实现了这个监听器。

在 使用观察者模式的时候,有很多的复杂问题需要注意。首先是可能出现内存泄露。监听的对象维护着一个观察者的引用。在监听对象释放这个引用之前,垃圾收集器 都不能删除观察者。一定要清醒的认识到这种可能,在合适的时候删除掉观察者。另外需要注意的是观察者对象维持在一个无序的集合之中。至少当注册监听器的时 候是这样。你没有必要知道先被注册的监听器是先被调用还是后被调用。如果你需要有序的调用,例如A必须先被调用然后是B。那么你必须引入一个中间层的对象来强制这种顺序。简单的按照顺序来注册监听器是不能确保调用顺序的。

Java平台中,另一个使用观察着模式的地方是Java消息服务(Java Message Service,JMSJMS的公共订购消息模型允许任何数量的订购者监听感兴趣的题目。当公共标题的信息产生的时候,所有相关的订购者都会被通知。

Java平台的其他地方也都用到了观察者模式,可见这一设计模式在这个领域广泛采用着。


http://www.linuxfans.org/nuke/modules.php?name=News&file=print&sid=1394
GUI编程-同步化的编程模型
GUI程序通常使用同步化的编程模型,也被称为“事件驱动编程”。
    这个意味着程序大部分时候时闲着的,等待由X服务器发送的事件,然后根据这些事件作出反应。事件可能时”用 户在点x,y处按下第一个按钮“,或者时”你控制的串口需要重画“。为了程序能够响应用户输入以及刷新请求,它需要在一个相当短的时间内处理每个事件(比 如作为一个大体的规则,小于200毫秒)
    这也意味着程序可能不执行在处理过程也许需要很长时间的事件的操作(例如打开一个连接到远程服务器的网络连接,或者连接到数据库服务器,甚至执行一个大文 件的拷贝)。而是,它需要同步化的执行所有这些操作。这可能通过使用各种同步模型来执行长时间的操作,或者通过用不同的进程或者线程来执行他们。



http://www-128.ibm.com/developerworks/cn/linux/server/clinic/part5/
事件是一个不同的并发概念,对管理 I/O 和相关的多任务职责很有用。
事件将异步的“外部动作”与编程上的回调(也称为信号、绑定等等)联系起来。

嵌入式操作系统及图形系统学习研究-『 UCGUI源码学习研究 』-[原创]UCGUI使用手册----中文翻译文档 下载
研究整合 uC/GUI+uC/OS+uC/FS+Lwip源代码成小型图形操作系统中,有挑战性,爽.......
网名:ucgui 邮件:ucgui@163.com QQ: 106719880
主页:http://www.ucgui.com
UCGUI研究学习群--12111753










 

 












 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值