版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第十十章 嵌入式Linux图形界面设计9.1 Linux图形开发基础 本节在介绍图形用户界面一般构架的基础上,详细讨论嵌入式图形用户界面开发常见的底层支持库和高级函数库。这些内容都是Linux图形界面开发的基础知识。GUI的一般架构图形用户界面GUI(Graphics User Interface)是迄今为止计算机系统中最为成熟的人机交互技术。一个好的图形用户界面的设计不仅要考虑到具体硬件环境的限制,而且还要考虑到用户的喜好等。由于图形用户界面的引入主要是从用户角度出发的,因此用户自身的主观感受对图形用户界面的评价占了很大比重,比如,易用性、直观性、友好性,等等。另外,从纯技术的角度看,仍然也
2、会有一些标准需要考虑,比如,跨平台性、对硬件的要求等。在嵌入式系统开发和应用中,我们所考虑的问题主要集中在图形用户界面对硬件的要求,以及对硬件类型的敏感性方面,在提供给用户的最终界面方面只是要求简单实用就够了。虽然不同的GUI系统因为其使用场合或服务目的不同,具体实现互有差异,但是总结起来,一般在逻辑上可以分为以下几个模块:底层I/O设备驱动(显示设备驱动、鼠标驱动、键盘驱动等)、基本图形引擎(画点、画线、区域填充)、消息驱动机制、高层图形引擎(画窗口、画按钮),以及GUI应用程序接口(API)。 底层I/O设备驱动,例如,显示驱动、鼠标驱动、键盘驱动等构成了GUI的硬件基础。由于此类设备的多
3、样性,需要对其进行抽象,并提供给上层一个统一的调用接口;而各类设备驱动则自成一体,形成一个GUI设备管理模块。当然,从操作系统内核的角度看,GUI设备管理模块则是操作系统内核的I/O设备管理的一部分。 基本图形引擎模块完成一些基本的图形操作,如画点、画线、区域填充等。它直接和底层I/O设备打交道,同时,多线程或者多进程机制的引入也为基本图形模块的实现提供了很大的灵活性。 消息不仅是底层I/O硬件和GUI上层进行交互的基础,同时也是各类GUI组件如窗口、按钮等相互作用的重要途径。一个GUI系统的消息驱动机制的效率对该系统的性能,尤其是对响应速度等性能的影响很大。 高级图形引擎模块则在消息传递机制
4、和基本图形引擎的基础上完成对诸如窗口、按钮等的管理。 GUI API则是提供给最终程序员的编程接口,使得他们能够利用GUI体系所提供的GUI高级功能快速开发GUI应用程序。另外,为了实现GUI系统,一般需要用到操作系统内核提供的功能,如线程机制、进程管理。当然,不可避免地需要用到内存管理、I/O设备管理,甚至还可能有文件管理。从用户的观点来看,图形用户界面(GUI)是系统的一个至关重要的方面:由于用户通过GUI与系统进行交互,所以GUI应该易于使用并且非常可靠。此外,它不能占用太多的内存,以便在内存受限的微型嵌入式设备上无缝执行。由此可见,它应该是轻量级的,并且能够快速装入。 嵌入式GUI要求
5、简单、直观、可靠、占用资源小且反应快速,以适应系统硬件资源有限的条件。另外,由于嵌入式系统硬件本身的特殊性,嵌入式GUI应具备高度可移植性与可裁减性,以适应不同的硬件条件和使用需求。总体来讲,嵌入式GUI具备以下特点: 体积小; 运行时耗用系统资源小; 上层接口与硬件无关,高度可移植; 高可靠性; 在某些应用场合应具备实时性。一个能够移植到多种硬件平台上的嵌入式GUI系统,应至少抽象出两类设备:基于图形显示设备(如VGA卡)的图形抽象层GAL(Graphic Abstract Layer)和基于输入设备(如键盘,触摸层等)的输入抽象层IAL(Input Abstract Layer)。GAL层
6、完成系统对具体的显示硬件设备的操作,最大限度地隐藏各种不同硬件的技术实现细节,为程序开发人员提供统一的图形编程接口。IAL层则需要实现对于各类不同输入设备的控制操作,提供统一的调用接口,如图9.2所示。GAL层与IAL层设计概念的引入,可以显著提高嵌入式GUI的可移植性。 嵌入式GUI底层支持库 1X Window2FrameBufferFrameBuffer是出现在2.2.xx内核中的一种驱动程序接口。由于Linux工作在保护模式,所以用户态进程无法像DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。在使用Fr
7、amebuffer时,Linux是将显卡置于图形模式下的。Framebuffer就是模仿显卡的功能,相当于抽象的显卡硬件结构,实现了通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反映在屏幕上。这种操作是抽象的、统一的。用户不必关心物理显存的位置、换页机制等具体细节,因为这些都是由Framebuffer设备驱动来完成的。FrameBuffer设备还提供了若干ioctl命令,通过这些命令,可以获得显示设备的一些固定信息(例如显示内存大小)、与显示模式相关的可变信息(例
8、如,分辨率、像素结构、每扫描线的字节宽度),以及伪彩色模式下的调色板信息等。通过FrameBuffer,还可以获得当前内核所支持的加速显示卡的类型(通过固定信息得到),这种类型通常是和特定显示芯片相关的。例如,目前最新的内核(2.4.9)中,就包含有对S3、Matrox、nVidia、3Dfx等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序可以将PCI设备的内存I/O(memio)映射到进程的地址空间。这些memio一般是用来控制显示卡的寄存器,通过对这些寄存器的操作,应用程序可以控制特定显卡的加速功能。但由于Framebuffer本身不具备任何运算数据的能力,只是一个提供显示内存
9、和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在FrameBuffer之上进行图形编程,还需要自己动手完成其他许多工作。举个例子来讲,FrameBuffer就像一张画布,使用什么样的画笔、如何画画,还需要用户自己动手完成。在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但由于所有显示任务都由CPU完成,因此CPU负担很重。 3SVGALibSVGALib是Linux系统中最早出现的非X图形支持库,是Linux下的VGA驱动函数库。虽然它的品质有点低,支援显卡种类也不多,但是有许多的游戏及程序都是用它来做开发,可以算是非官方的标准了。这个
10、库从最初对标准VGA兼容芯片的支持开始,已经发展到对老式SVGA芯片,以及现今流行的高级视频芯片的支持。它为用户提供了在控制台上进行图形编程的接口,使用户可以在PC兼容系统上方便地获得图形支持。但该系统也存在一些不足: SVGALib从最初的vgalib发展而来,保留了老系统的许多接口,而这些接口却不能良好地适应新显示芯片的图形能力。 未能较好地隐藏硬件细节。许多操作,不能自动使用显示芯片的加速能力支持。 可移植性差。SVGALib目前只能运行在x86平台上,除Alpha平台,对其他平台的支持能力较差。 SVGALib作为一个老的图形支持库,目前的应用范围越来越小,尤其在Linux内核增加了F
11、rameBuffer驱动支持之后,有逐渐被其他图形库替代的趋势。4LibGGILibGGI是一个跨平台的绘图库,可以建立一个一般性的图形接口,这个抽象接口连同相关的输入(鼠标、键盘、游戏杆等)接口一起,可以方便地运行在X Window、SVGALib、FrameBuffer等之上。建立在LibGGI之上的应用程序,不经重新编译,就可以在上述这些底层图形接口上运行。在Linux上,LibGGI是通过调用FrameBuffer或SVGALib来完成图形操作的,可能速度比较慢。但在某些不支持FrameBuffer或vga的系统上,采用LibGGI仍然是一种不错的选择。 嵌入式GUI高级函数库 1Xl
12、ib及其他相关函数库在X Window系统中进行图形编程时,可以选择直接使用Xlib。Xlib实际上是对底层 X 协议的封装,可通过该函数库进行一般的图形输出。如果用户的X Server支持DGA,则可以通过DGA扩展直接访问显示设备,从而获得加速支持。2SDL(Simple DirectMedia Layer)SDL是一个跨平台的多媒体游戏支持库。其中包含了对图形、声音、游戏杆、线程等的支持,目前可以运行在许多平台上。SDL支持图形的功能强大,高级图形处理能力尤为突出,可以实现Alpha混合、透明处理、YUV覆盖、Gamma校正等。在SDL环境中能够非常方便地加载支持OpenGL的Mesa库
13、,从而提供对二维和三维图形的支持。3AllegroAllegro是一个专门为x86平台设计的游戏图形库。最初的Allegro运行在DOS环境下,目前也可运行在Linux FrameBuffe控制台、Linux SVGALib、X Window等系统上。Allegro提供了丰富的图形功能,包括矩形填充和样条曲线生成等,而且具有较好的三维图形显示能力。由于Allegro的许多关键代码是采用汇编编写的,所以该函数库具有运行速度快、占用资源少的特点。4Mesa3DMesa3D是一个兼容OpenGL规范的开放源码函数库,是目前Linux上提供专业三维图形支持的惟一选择。Mesa3D也是一个跨平台的函数库
14、,能够运行在X Window、X Window with DGA、BeOS、Linux SVGALib等平台上。5DirectFBDirectFB是特别为Linux FrameBuffer加速的一个图形库,正在尝试建立一个兼容GTK(GIMP Toolkit)的嵌入式GUI系统。9.2 嵌入式Linux图形用户界面简介 Qt/Embedded(简称QtE)是一个专门为嵌入式系统设计的图形用户界面的工具包,由挪威Trolltech公司开发,最初作为跨平台的开发工具用于Linux台式机。它支持各种有UNIX 和Microsoft Windows特点的系统平台。Qt/Embedded以原始Qt为基础
15、,许多基于Qt的X Window程序可以非常方便地移植到Qt/Embedded上,因此,自从Qt/Embedded以GPL条款形式发布以来,就有大量的嵌入式Linux开发商转到了Qt/Embedded系统上,比如,韩国的Mizi公司。Qt/Embedded通过Qt API与Linux I/O设备直接交互,是面向对象编程的理想环境。面向对象的体系结构使代码结构化、可重用并且运行快速,与其他GUI相比,Qt GUI非常快,没有分层,这使得Qt/Embedded成为基于Qt的程序的最紧凑环境。Qt/Embedded延续了Qt在X上的强大功能,在底层摒弃了X lib,仅采用FrameBuffer作为底
16、层图形接口。同时,将外部输入设备抽象为keyboard和mouse输入事件,底层接口支持键盘、GPM鼠标、触摸屏,以及用户自定义的设备等。Qt/Embedded类库完全采用C+封装,丰富的控件资源和较好的可移植性是Qt/Embedded最为突出的优点。它的类库接口完全兼容于同版本的Qt-X11,使用X下的开发工具可以直接开发基于Qt/Embedded的应用程序GUI。 Qt/EmbeddedMicrowindows/Nano-X Microwindows是Century Software的开放源代码项目,设计用于带小型显示单元的微型设备。它有许多针对现代图形视窗环境的功能部件,可被多种平台支持
17、。Microwindows体系结构是基于客户机/服务器(Client/Server)分层设计的。最底层是屏幕和输入设备,通过驱动程序来与实际硬件交互;中间层提供底层硬件的抽象接口,进行窗口管理;最上层支持两种API:第一种支持Win32/WinCE API,称为Microwindows,另一种支持的API与GDK(GTK+ Drawing Kit)非常相似,用在Linux上称为Nano-X,用于占用资源少的应用程序。Microwindows支持1、2、4和8bpp(每像素的位数)的衬底显示,以及8、16、24和32 bpp的真彩色显示。Microwindows提供了相对完善的图形功能和一些高级
18、的特性,如Alpha混合、三维支持和TrueType字体支持等。该系统为了提高运行速度,也改进了基于Socket套接字的X实现模式,采用基于消息机制的Server/Client传输机制。Microwindows还支持速度更快的帧缓冲区。Nano-X服务器占用的存储器资源大约在100KB150KB。原始Nano-X应用程序的平均大小在30KB60KB。与Xlib的实现不同,Nano-X仍在每个客户机上同步运行,这意味着一旦发送了客户机请求包,服务器在为另一个客户机提供服务之前一直等待,直到整个包都到达为止。这使服务器代码非常简单,而运行的速度仍非常快。 MiniGUIMiniGUI是自由软件项目
19、(遵循LGPL条款发布),其目标是为基于Linux的实时嵌入式系统提供一个轻量级的图形用户界面支持系统。MiniGUI为实时嵌入式操作系统提供了完善的图形及图形用户界面支持。可移植性设计使得它不论在哪个硬件平台、哪种操作系统上运行,均能为上层应用程序提供一致的应用程序编程接口(API)。在MiniGUI几年的发展过程中,有许多值得一提的技术创新点包括: 图形抽象层。图形抽象层对顶层API基本没有影响,但大大方便了MiniGUI应用程序的移植、调试等工作。目前包含三个图形引擎,SVGALib、LibGGI,以及直接基于Linux FrameBuffer的Native Engine。 多字体和多字
20、符集支持。这部分通过设备上下文(DC)的逻辑字体(LOGFONT)实现,不管是字体类型还是字符集,都可以非常方便地进行扩充。应用程序在启动时,可切换系统字符集,比如GB、BIG5、EUCKR、UJIS。MiniGUI的这种字符集支持,这种实现更适合于嵌入式系统。 两个不同架构的版本。最初的MiniGUI运行在PThread库之上,这个版本适合于功能单一的嵌入式系统,但存在系统健壮性不够的缺点。在0.9.98版本中,引入了MiniGUI-Lite版本,这个版本在提高系统健壮性的同时,通过一系列创新途径,避免了传统C/S结构的弱点,为功能复杂的嵌入式系统提供了一个高效、稳定的GUI系统。在Mini
21、GUI 1.1.0版本的开发中,参照SDL和Allegro的图形部分,重新设计了图形抽象层,增强了图形功能,同时增强了MiniGUI-Lite版本的某些特性。增强的MiniGUI-Lite支持层的设计,同一层可以容纳多个同时显示的客户程序,并平铺在屏幕上显示。新的GAL支持硬件加速能力,并能够充分使用显示内存;新GAL之上的新GDI接口得到进一步增强,可以支持Alpha混合、透明位块传输、光栅操作、YUV覆盖、Gamma校正,以及高级图形功能(椭圆、多边形、样条曲线),等等。 OpenGUIOpenGUI在Linux系统上已经应用很长时间了。OpenGUI基于一个用汇编实现的x86图形内核,提
22、供了一个快速、32位、高层的C/C+图形接口。OpenGUI也是一个公开源码(LGPL)项目,最初的名字叫FastGL,只支持256色的线性显存模式。目前,OpenGUI也支持其他显示模式,并且支持多种操作系统平台,比如,MS-DOS、QNX和Linux,等等,不过目前只支持x86硬件平台。OpenGUI也分为三层:最低层是由汇编编写的快速图形引擎;中间层提供了图形绘制API,包括线条、矩形、圆弧等,并且兼容于Borland的BGI API;第三层用C+编写,提供了完整的GUI对象集。OpenGUI提供了消息驱动的API和BMP文件格式支持,OpenGUI比较适合基于x86平台的实时系统,可移
23、植性稍差,目前的发展也基本停滞。 9.3Qt/Embedded嵌入式图形开发基础开发Qt的挪威TrollTech公司,主要开发两种产品,提供给嵌入式Linux开发的应用程序平台和跨平台应用程序界面框架,Qtopia和Qt分别是其中具有代表性的两个。Qtopia是第一个面向嵌入式Linux的全方位应用程序开发平台,已经应用于众多基于Linux的PDA(个人数字助理)设备和智能电话。Qtopia环境包括一个程序发布器和一套支持应用程序开发的程序和库,它还有灵活的输入处理器,包括手写识别、选择板和虚拟键盘,可以很容易地编写新的输入法。Qtopia是夏普公司的Zaurus PDA(如图9.5所示)使用
24、的标准环境。 Qt是一个跨平台C+应用程序开发框架,可以编写单一代码的应用程序,并可在Windows,Linux,UNIX,Mac OS X和嵌入式Linux等不同平台上进行本地化运行,是开放源代码KDE桌面环境的基础。目前,Qt已被成功应用于商业应用程序的开发。Qt作为Linux桌面环境KDE的基础,与Windows下的MFC类似,Qt的类库等价于MFC的开发库。但是Qt的类库封装了适应不同操作系统的访问细节,支持跨平台的类库,这种优点使得Qt的应用非常广泛。目前Qt可以支持现有的多种操作系统平台,主要有: MS/Windows 95、Windows 98、WindowsNT 4.0、Win
25、dows 2000、Windows XP; Unix/X11 Linux、Sun Solaris、HP-UX、Compaq True64Unix、IBM AIX、SGI IRIX和很多其他X11平台; Macintoshi Mac OS X; 带FrameBuffer的嵌入式Linux平台。 Qt/Embedded概述 Qt/Embedded是一个为嵌入式应用定制的用于多种平台图形界面程序开发的C+工具包,以原始Qt为基础,做了许多适用于嵌入式环境的调整,是面向对象编程的理想环境。Qt/Embedded通过Qt API与Linux I/O设备直接交互,面向对象的体系结构使代码结构化、可重用并且
26、运行快速。与其他GUI相比,Qt GUI非常快,没有分层结构,这使得Qt/Embedded成为运行基于Qt的程序的最紧凑环境。Qt/Embedded为带有轻量级窗口系统的嵌入式设备提供了标准的Qt API。面向对象的设计思想,使得它能很好地支持键盘、鼠标和图形加速卡这样的附加设备。通过使用Qt/Embedded,开发者可以感受到在Qt/X11、Qt/Windows和Qt/Mac等不同的版本下使用相同的API编程所带来的便利。1Qt的体系结构Qt的功能建立在所支持平台底层的API上,这使得Qt灵活而高效。Qt是一个“模拟的”多平台工具包,所有窗口部件都由Qt绘制,可以通过重新实现其虚函数来扩展或
27、自定义部件功能。Qt为所支持平台提供底层API,这不同于传统分层的跨平台工具包(如Windows中的MFC)。 Qt是受专业支持的,它可以利用了以下平台:Microsoft Windows、X11、Mac OS X和嵌入式Linux。它使用单一的源代码树,只需简单的在目标平台上重编译就可以把Qt程序转换成可执行程序。Qt/Embedded与Qt/X11的Linux版本的比较如图9.6所示。 Qt/X11使用Xlib与X服务器直接通信,而不使用Xt(X Toolkit)、Motif、Athena或其他工具包。Qt能够自动适应用户的窗口管理器或桌面环境,并且拥有Motif、SGI、CDE、GNOM
28、E和KDE的外观。这与大多数其他的UNIX工具包形成鲜明对比,那些工具包常将用户锁定为它们自己的外观。Qt/Embedded提供了完整的窗口环境,可以直接写入Linux的帧缓存。Qt/Embedded去掉了对X服务器的依赖,而且运行起来比基于X11的Linux设备更快、更省内存。虽然Qt是一个多平台工具包,但是客户会发现它比个别平台上的工具包更易学、也更有用。许多客户用Qt进行单一平台的开发,因为他们喜欢Qt完全面向对象的做法。2窗口系统一个Qt/Embedded窗口系统包含了一个或多个进程,其中的一个进程可作为服务器,这个服务进程会分配客户显示区域,以及产生鼠标和键盘事件。同时,这个服务进程
29、还能为已经运行的客户程序提供输入方法和用户接口,这个服务进程其实也就是一个有某些额外权限的客户进程。任何程序都可以在命令行上加上“-qws”的选项来把它作为一个服务器运行。客户与服务器之间的通信使用共享内存的方法实现,通信量应该保持最小。例如,客户进程直接访问帧缓冲来完成全部的绘制操作,而不会通过服务器,客户程序需要负责绘制它们自己的标题栏和其他式样。这就是Qt/Embedded库内部层次分明的处理过程。Qt/Embedded支持4种不同的字体格式:True Type(TTF)、Postscript Typel、位图发布字体(BDF)和Qt的预呈现(Pre-rendered)字体(QPF)。Q
30、t还可以通过增加QFontFactory的子类来支持其他字体,也可以支持以插件方式出现的反别名字体。Qt/Embedded支持几种鼠标协议:BusMouse、IntelliMouse、Microsoft和MouseMan。通过QWSMouseHandler或QcalibratedMouseHandler派生子类,可以支持更多的客户指示设备。通过QWSKeyboardMouseHandler,可以支持更多的客户键盘和其他非指示设备。 在一个无键盘的设备上,输入法成了惟一的字符输入手段。Qtopia提供了4种输入法:笔迹识别器、图形化的标准键盘、Unicode键盘和基于字典方式提取的键盘。创建Qt
31、/Embedded开发环境 基于Qt/Embeded开发的应用程序最终会发布到安装有嵌入式Linux操作系统的小型设备上,使用Linux操作系统的PC或者工作站来完成Qt/Embedded开发是最理想的环境。1软件安装包 tmake-1.11.tar; qt-embedded-2.3.7.tar; qt-x11-2.3.2.tar; qtopia-free-1.7.0.tar。首先准备软件安装包:tmake工具安装包、qt-embedded安装包、qt-x11安装包和具有友好人机界面的qtopia-free安装包。把软件包下载到提前建立的x86-qtopia目录下。为防止版本的不同所造成的冲突
32、,选择软件包时需要注意一些基本原则,因为qt-x11安装包的两个工具uic和designer产生的源文件会与qt-embedded库一起被编译链接,本着向前兼容的原则,qt-x11安装包的版本必须比qt-embedded安装包的版本旧。在Trolltech公司的网站上可以下载该公司所提供的Qt/Embedded的免费版本。2安装tmake在Linux命令模式下运行以下命令:tar xfz tmake-1.11.tar.gzexport TMAKEDIR=$PWD/tmake-1.11export TMAKEPATH=$TMAKEDIR/lib/qws/linux-x86-g+export PA
33、TH=$TMAKEDIR/bin:$PATH 3安装Qt/Embedded2.3.7在Linux命令模式下运行以下命令:tar xfz qt-embedded-2.3.7.tar.gzcd qt-2.3.7export QtDIR=$PWDexport QtEDIR=$QtDIRexport PATH=$QtDIR/bin:$PATHexport LD_LIBRARY_PATH=$QtDIR/lib:$LD_LIBRARY_PATHcp $QPEDIR/src/qt/qconfig-qpe.h src/tools/./configure -qconfig qpe -qvfb -depths 4
34、,8,16,32make sub-srccd .“./configure -qconfig qpe -qvfb -depths 4,8,16,32”指定Qt嵌入式开发包生成虚拟缓冲帧工具qvfb,并支持4、8、16、32位的显示颜色深度。也可以在configure的参数中添加-system-jpeg和gif,使Qtopia平台能支持jpeg、gif格式的图形。“make sub-src”指定按精简方式编译开发包。4安装Qt/X11 2.3.2在Linux命令模式下运行以下命令:tar xfz qt-x11-2.3.2.tar.gzcd qt-2.3.2export QtDIR=$PWDexpo
35、rt PATH=$QtDIR/bin:$PATHexport LD_LIBRARY_PATH=$QtDIR/lib:$LD_LIBRARY_PATH./configure -no-openglmakemake -C tools/qvfbmv tools/qvfb/qvfb bincp bin/uic $QtEDIR/bincd .根据开发者本身的开发环境,也可以在configure的参数中添加其他参数,比如,-no-opengl或-no-xfs,可以键入./configure -help来获得一些帮助信息。 5安装Qtopia在Linux命令模式下运行以下命令:tar xfz qtopia-f
36、ree-1.7.0.tar.gzcd qtopia-free-1.7.xexport QtDIR=$QtEDIRexport QPEDIR=$PWDexport PATH=$QPEDIR/bin:$PATHcd src./configuremakecd ./.6安装Qtopia桌面cd qtopia-free-1.7.x/srcexport QtDIR=$QtEDIR./configure -qtopiadesktopmakemv qtopiadesktop/bin/qtopiadesktop ./bincd .为了方便使用,我们把以上各步骤的操作编译成了build脚本,内容如下所示:#!/b
37、in/bashtar xfvz tmake-1.11.tar.gztar xfvz qt-embedded-2.3.7.tar.gztar xfvz qtopia-free-1.7.0.tar.gztar xfvz qt-x11-2.3.2.tar.gzmv tmake-1.11 tmakemv qt-2.3.7/ qtmv qtopia-free-1.7.0 qtopiamv qt-2.3.2 qt-x11cd qt-x11export QtDIR=$PWDecho yes | ./configure -static -no-xft -no-opengl -no-smmake -C src/
38、moccp src/moc/moc binmake -C srcmake -C tools/designermake -C tools/qvfbcp tools/qvfb/qvfb binstrip bin/uic bin/moc bin/designer bin/qvfbcd .cp qt-x11/bin/?* qt/binrm -fr qt-x11export QtDIR=$PWD/qtexport QPEDIR=$PWD/qtopiaexport TMAKEDIR=$PWD/tmakeexport TMAKEPATH=$TMAKEDIR/lib/qws/linux-generic-g+e
39、xport PATH=$QtDIR/bin:$QPEDIR/bin:$TMAKEDIR/bin:$PATHcd qtmake cleancp ./qtopia/src/qt/qconfig-qpe.h src/tools/(echo yes; echo yes ) |./configure -platform linux-generic-g+ -qconfig qpe -depths 16,24,32 make -C srccd .cd qtopia/src./configure -platform linux-generic-g+make然后进入x86-qtopia目录执行生成命令:$./b
40、uild$ldconfig运行ldconfig是为了使生成的qt和qtopia库有效,运行一次即可。根据上面的步骤安装完成Qt/Embedded和Qtopia之后,就可以运行这些程序了。运行Qt的虚拟仿真窗口:在Linux的图形模式下运行命令qvfb&;运行Qtopia,在图形模式下运行命令:export QtDIR=$QtEDIR,qpe &这样,Qtopia的程序就运行在Qt的虚拟仿真窗口(QVFB)上。Qt/Embedded的使用 1信号与槽信号与槽提供了对象间通信的机制。它们易懂易用,并且Qt设计器能够完整支持。图形用户接口的应用程序能响应用户的动作。例如,当用户单击一个菜单项或工具栏
41、按钮时,程序就会执行某些代码。大多数情况下,我们需要不同的对象之间能够通信。程序员必须将事件与相关的代码关联起来。以前的开发工具包使用的事件响应机制很容易崩溃、不够健全,同时也不是面向对象的。而Trolltech发明了一套叫做“信号与槽”的解决方案。信号与槽是一种强有力的对象间通信机制,这种机制既灵活,又面向对象,并且用C+来实现,完全可以取代传统工具中的回调和消息映射机制。以前,使用回调函数机制关联某段响应代码和一个按钮的动作时,需要将相应代码函数指针传递给按钮。当按钮被单击时,函数被调用。对于这种方式不能保证回调函数被执行时传递的参数都有着正确的类型,很容易造成进程崩溃。并且回调方式将GU
42、I元素与其功能紧紧地捆绑在一起,使开发独立的类变得很困难。Qt的信号与槽机制则不同,Qt的窗口在事件发生后会激发信号。例如,当一个按钮被单击时会激发clicked信号。程序员通过创建一个函数(称做一个槽)并调用connect()函数来连接信号,这样就可以将信号与槽连接起来。信号与槽机制不需要类之间相互知道细节,这使得开发代码可高度重用的类变得更加容易。因为这种机制是类型安全的,类型错误被当成警告并且不会引起崩溃。信号与槽连接的示意图如图9.8所示。如果一个退出按钮的clicked()信号被连接到一个应用程序的退出函数quit()槽,用户就可以单击退出键来终止这个应用程序。代码可以这样写:con
43、nect(button.SIGNAL(clicked(),qApp,SLOT(quit(); 在Qt程序执行期间,是可以随时增加或撤销信号与槽的连接的。它是类型安全的,可以重载或重新实现,并且可以在类的public、protected或private区出现。例9.1:信号与槽连接的一个实例。如果要使用信号与槽机制,一个类必须继承QObject或它的一个子类,并且在定义这个类时包含Q_OBJECT宏。信号在signals区间里声明,而槽可以在public slots,protected slots或private slots区间声明。以下是子类化QObject的一个例子:class BankAc
44、count : public QObject Q_OBJECTpublic: BankAccount() curBalance = 0; int balance() const return curBalance; public slots: void setBalance( int newBalance );signals: void balanceChanged( int newBalance );private: int curBalance;BankAccount类有一个构造器,获取函数balance()和设置函数setBalance()。这个类还有一个balanceChanged()
45、信号,用来声明它在BankAccount类的成员curBalance的值改变时产生。信号不需要被实现,当信号被激发时,连接到它的槽就会执行。设置函数作为一个槽在public slots区间声明,槽是能像其他函数一样被调用,也能与信号相连接的成员函数。以下是setBalance()的实现:void BankAccount:setBalance(int newBalance) if(newBalance!=curBalance) curBalance=newBalance; emit balanceChanged(curBalance); 其中,语句emit balanceChanged(curB
46、alance)作用是当curBalance的值改变时,将新的curBalance值作为参数去激活信号balanceChanged()。关键字emit跟信号和槽一样是Qt提供的,会被C+预处理器转换成标准的C+代码。 例9.2:这是一个怎样连接两个BankAccount对象的实例:BankAccount x,y;connect(&x,SIGNAL(balanceChanged(int),&y,SLOT(setBalance(int);x.setBalance(2450);当x的balance被设置为2450时,balanceChanged()信号被激发,这个信号被y的setBalance()槽接
47、收后,y的balance也被设置为2450。一个对象的信号可以连接到许多不同的槽,多个信号也可以连接到特定对象的一个槽。连接在具有相同参数的信号与槽之间建立,槽的参数可以比信号少,多余的参数会被忽略。信号与槽机制是在标准C+中实现的,是使用Qt工具包中的C+预处理器和元对象编译器(Meta Object Compiler,moc)来实现的。moc读取程序头文件并产生必要的支持信号与槽机制的代码。qmake产生的Makefiles会将moc自动加入进去,开发者无需编辑甚至无需查看这些产生的代码。 2窗口部件Qt拥有一系列能满足不同需求的窗口部件,如按钮、滚动条等。Qt的窗口部件使用很灵活,能够适
48、应子类化的特殊要求。Qt中有3个主要的基类:QObject、QTimer和QWidget。窗口部件是QWidget或其子类的实例,自定义的部件则通过子类继承得来,继承关系如图9.9所示。 (1)基本部件。一个窗口部件可包含任意数量的子部件。子部件在父部件的区域内显示。没有父部件的部件是顶级部件(比如一个窗口),Qt不在窗口部件上施加任何限制。任何部件都可以是顶级部件;任何部件都可以是其他部件的子部件。通过使用布局管理器可以自动设定子部件在父部件区域中的位置,如果喜欢也可以手动设定。如果父部件被停用、隐藏或删除后,同样的动作会递归地应用于它的所有子部件。标签、消息框、工具提示等并不局限于使用同一
49、种颜色、字体和语言。通过使用HTML的一个子集,Qt的文本渲染部件能够显示多语言宽文本,下面是一个实例代码:#include #include int main( int argc, char *argv ) QApplication app( argc, argv ); QLabel *hello = new QLabel( Hello Qt/Embedded!, 0 ); app.setMainWidget( hello ); hello-show(); return app.exec();这是我们接触到的第一个Qt程序,为了使大家便于理解,对程序的代码一行一行地解说。#include 这
50、一行引用了包含QApplication类定义的头文件。在每一个使用Qt的应用程序中都必须使用一个QApplication对象。QApplication管理了各种各样的应用程序的广泛资源,比如默认的字体和光标,等等。#include 引用了包含QLabel类定义的头文件,因为本例使用了QLabel对象。QLabel可以像其他QWidget一样管理自己的外形。一个窗口部件就是一个可以处理用户输入和绘制图形的用户界面对象。程序员可以改变它的全部外形和其他属性,以及这个窗口部件的内容。 int main( int argc, char *argv )main()函数是程序的入口。在使用Qt的所有情况下
51、,main()只需要在把控制转交给Qt库之前执行一些初始化,然后Qt库通过事件来向程序告知用户的行为。argc是命令行变量的数量,argv是命令行变量的数组,这是一个C/C+特征。QApplication app( argc, argv );app是这个程序的Qapplication,它在这里被创建并且处理命令行变量。所有被Qt识别的命令行参数都会从argv中被移除,并且argc也因此而减少。在任何Qt的窗口系统部件被使用之前必须创建QApplication对象。QLabel *hello = new QLabel( Hello Qt/Embedded!, 0 );这里是在QApplicati
52、on之后接着的是第一个窗口系统代码,创建了一个标签。这个标签被设置成显示“Hello Qt/Embedded!”并且字体颜色为蓝色,“Qt/Embedded!”为斜体。因为构造函数指定0为它的父窗口,所以它自己构成了一个窗口。app.setMainWidget( &hello );这个按钮被选为这个应用程序的主窗口部件。如果用户关闭了主窗口部件,应用程序就退出了。设置主窗口部件并不是必须的步骤,但绝大多数程序都会这样做。hello.show();当创建一个窗口部件的时候,它是不可见的。必须调用show()来使它变为可见的。return app.exec();这里就是main()把控制转交给Qt
53、,并且当应用程序退出的时候exec()就会返回。在exec()中,Qt接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。 (2)画布。QCanvas类提供一个2D图形的高级接口。它能够处理大量的画布项目来描述直线、矩形、椭圆、文本、位图,以及动画等。画布项目很容易做成交互式界面,例如,支持用户移动等。画布项目是QCanvasItem子类的实例。它们比窗口部件轻巧得多,能很快地移动、隐藏和显示。QCanvas可以有效地支持冲突检测,还能罗列出指定区域中的所有画布项目。QCanvasItem可以被子类化,用以提供自定义的项目类型或扩充已有类型的功能。QCanvas对象由QCanvasVie
54、w对象绘制,QCanvasView对象能以不同的译文、比例、角度和剪切方式显示同一个QCanvas。QCanvas是数据表现方式的典范,它可被用来绘制路线地图和展示网络拓扑,也适合开发快节奏有大量角色的2D游戏。(3)自定义窗口部件。通过对QWidget或它的一个子类进行子类化,我们可以创建自己的窗口部件或对话框。为了举例说明子类化,下面提供了数字钟部件的完整代码。如图9.16所示为数字钟图片显示。数字钟部件是一个能显示当前时间并自动更新的LCD,冒号分隔符随秒数的流逝而闪烁。 Clock在clock.h中这样定义:#include class Clock:public QLCDNumberp
55、ublic: Clock(QWidget *parent=0,const char *name=0);protected: void timerEvent(QTimerEvent *event);private: void showTime(); bool showingColon;Clock从QLCDNumber部件继承了LCD功能。它有一个典型部件类所拥有的典型构造函数,带有可选parent和name参数。系统有规律地调用从QObject继承的timerEvent()函数。clock.h中声明的函数在clock.cpp中实现:#include #include clock.hClock:C
56、lock(QWidget *parent,const char *name) :QLCDNumber(parent,name),showingColon(true)showTime();startTimer(1000);void Clock:timerEvent(QTimerEvent *)showTime();void Clock:showTime()QString timer=QTime:currentTime().toString().left(5);if(!showingColon)time2= ;display(time);showingColon=!showingColon;构造函
57、数调用showTime()显示当前时间来初始化钟表,并且告诉系统每1000毫秒调用一次timerEvent()来刷新LCD的显示。在showTime()中,通过调用QLCDNumber:display()来显示当前时间。每次调用showTime()来让冒号闪烁时,冒号就被空白代替。文件clock.h和clock.cpp完整地声明并实现了Clock部件,这个部件可立即投入使用。#include #include clock.hint main(int argc,char *argv)QApplication app(argc,argv);Clock *clock=new Clock;app.se
58、tMainWidget(clock);clock-show();return app.exec();这个样例程序包括了单个部件(数字钟)并且没有子部件。通过布局来联合部件可以产生复杂部件。如果需要也可以从头开始编写自己的部件。例如,要创建一个类似于钟表的部件,可能需要在代码中绘制钟面和指针而不是依靠已经实现的基本类。 3主窗口QMainWindow类为应用程序提供了一个典型的主窗口框架。一个主窗口包括一系列标准部件,顶部包含一个菜单栏,菜单栏下放置这一个工具栏,在主窗口的下方有一个状态栏。工具栏可以任意放置在中心区域的四边,也可以拖拽到工具栏区域以外,作为独立的浮动工具托盘。QToolButt
59、on类实现了具有一个图标,一个3D框架和一个可选标签的工具栏按钮。切换型工具栏按钮可以打开或关闭某些特征,其他的按钮则会执行一个命令,也能触发弹出式菜单。QToolButton可以为不同的模式(活动、关闭、开启等)和状态(打开、关闭等)提供不同的图标。如果只提供一个图标,Qt能根据可视化线索自动地辨别状态,例如,将禁用的按钮变灰。QToolButton通常在QToolBar内并排出现。一个程序可含有任意数量的工具栏并且用户可以自由移动它们。工具栏可以包括几乎所有部件,例如,QComboBox和QSpinBox。主窗口的中间区域可以包含多个其他窗体。4菜单弹出式菜单QpopupMenu类在一个垂
60、直列表里面向用户呈现菜单项,它可以是单独的(如背景菜单),可以出现在菜单栏里,也可以是另一个弹出式菜单的子菜单。菜单项之间可以用分隔符隔开。每个菜单项可以有一个图标、一个复选框和一个快捷键。菜单项通常会响应一个动作(比如,保存)。分隔符通常显示为一条线,用来可视化地分组相关的动作。下面是一个创建了New、Open、Exit菜单项的文件菜单的例子:QPopupMenu *fileMenu=new QPopupMenu(this);fileMenu-insertItem(&New,this,SLOT(newFile(),CTRL+Key_N);fileMenu-insertItem(&Open.,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026医院文员年终工作总结
- 睡眠与健康第八章睡眠与梦
- 课程改革与教育的和谐发展
- T-SPPHN 009-2025 田间释放中华淡翅盲蝽防治稻飞虱技术规程
- 事业单位教育岗巩固自测题含解析
- 环境岗2026事业编面试自测卷含解析
- 农业岗2026事业编面试自测卷模拟练习配套答题思路
- 福建文旅岗2026面试模拟练习含答案含解析配套答题思路
- 计算教学的有效指导
- 课题2溶解度饱和溶液和不饱和溶液
- 2026年新版预防未成年人犯罪法知识竞赛题库及参考答案
- 2026年水务集团招聘考试笔试试题及答案
- 2026年甘肃省酒泉市金塔县招聘社区工作者考试参考题库及答案解析
- 2026年云南云上云大数据产业发展有限公司及下属子公司第一次社会招聘(32人)笔试模拟试题及答案详解
- 冠状动脉粥样硬化性心脏病患者药物治疗管理路径专家共识
- 纺织厂安全生产管理制度
- 2026中国新能源电池技术研发行业市场现状趋势分析投资策略规划报告
- 2026秋沪教牛津版五年级上英语单词默写(默写)
- 苏教版六年级上册数学《比的意义》教学设计
- JJF(吉)106-2022 水分接收器校准规范
- 中药饮片调剂规范考核试题及答案
评论
0/150
提交评论