嵌入式Qt

2024-07-03

嵌入式Qt(共7篇)

嵌入式Qt 篇1

摘要:介绍了一种基于嵌入式Linux操作系统的小型通用智能控制器的图形用户界面的设计,着重阐述了使用跨平台开发工具Qt/Embedded的开发过程。

关键词:嵌入式Linux,ARM9,Qt/Embedded,智能控制器,嵌入式GUI

随着嵌入式系统的发展及市场的不断扩大,人们对嵌入式人机交互界面的需求越来越多,要求也越来越高。嵌入式系统或实时系统对图形用户界面(Graphical User Interface,GUI)的基本要求包括轻型、占用资源少、高性能、高可靠性以及可配置等特点,对嵌入式人机交互界面的设计是整个开发过程中必不可少的环节[1]。友好的人机界面往往决定了嵌入式产品能否成功打入市场,因此图形用户界面的开发是产品开发过程中最耗时的工作[2]。为此,笔者针对工业现场中一种通用嵌入式智能控制器,设计了一款具有通用控制功能的图形用户界面。

1 系统结构框架

控制系统由软件和硬件两部分组成(图1)。硬件是一个小型的智能控制器,它采用ARM嵌入式微处理器作为控制核心,将数据采集模块采集的数据进行处理,再将处理后的数据发送给数据输出模块,之间的数据发送与接收都是通过SPI总线模块完成的;显示和操作部分都可以通过图形化的界面在彩色液晶触摸屏上完成,同时为了能进行远程在线实时访问,该控制器还有GPRS模块,将数据发送给上位机。软件部分将采集来的数据进行处理,使用户可以根据实际现场需要配置各通道的数据,还可以对数据进行实时监测与显示,必要的话还可以添加GPRS模块及参数配置等。

2 开发过程

开发过程中所使用的硬件平台处理器是SANSUNG公司的16/32位的RISC微处理器S3C2440,它为手持设备和一般类型的应用提供了低价格、低功耗、高性能的解决方案[3]。数据采集和输出模块将现场采集的信号和数据通过整流、调理及隔离等处理转化成标准信号,再通过SPI总线传送给S3C2440,同时还带有一块七寸液晶显示屏和触摸屏,提高了系统的交互性。GPRS模块选用的是中兴的ME3000,它具有体积小、通讯可靠稳定、价格适中的优点;支持短消息业务,内嵌TCP/IP协议和标准的AT命令,通过AT命令进行语音和数据通讯[4]。控制器BIOS采用基于三星原来的bootloader之vivi改进而来的Surpervivi,移植了Linux-2.6.29的内核,交叉编译工具为arm-linux-gcc-4.1.2。

2.1 开发环境的建立

系统软件的开发采用的是目标机——宿主机的形式。首先在进行开发的宿主机(PC机)上建立Linux编译环境,然后根据目标机的硬件种类对Qt应用程序源码包进行定制,进而交叉编译生成相关函数库,最后制作根文件系统下载到目标板上。

小型智能控制器采用的是嵌入式Linux操作系统。该技术逐渐趋于成熟,系统的定制越发方便,可以支持更多平台,具有以下特点:精简的内核,适用于不同的CPU,支持多种体系结构;针对嵌入式的存储方案;用户可定制,可提供图形化的定制和配置工具;常用嵌入式芯片的驱动集,支持大量的周边硬件设备,驱动丰富[5]。Linux比较常见的版本有RedHat、Fedora、Ubuntu和SUSE Linux。在宿主机的VMware虚拟机上安装的是RedHat Enterprise Linux 5.1。由于系统要求良好的图形用户界面,因此需要一个强大的图形编程工具,综合考虑采用的是Qt。基本上,Qt 同 X Window 上的 Motif、Openwin、GTK 等图形界面库及 Windows 平台上的 MFC、OWL、VCL、ATL 属于同类型,但是 Qt 具有良好的跨平台特性、面向对象、丰富的API、支持2D/3D图像渲染以及大量的开发文档等优点[6]。是为嵌入式设备上的图形用户接口和应用开发而定制的C++开发包。

首先从网上下载免费的Qt/Embedded开发包,本系统采用的是Qt/E4.6.3版。将压缩包解压成3份,分别编译成PC版、嵌入式x86和嵌入式ARM。需要注意编译PC版和嵌入式x86之后要编译PC版中的qvfb,这里提到的qvfb是为Qt做的一个虚拟frambuffer的应用程序,它的最终目的就是把Qt应用程序运行的结果显示在qvfb上,避免了一些小的改动来回烧写根文件系统从而提高研发时的工作效率;由于本系统中有触摸屏,为了添加对触摸屏的支持,在编译嵌入式ARM版之前先编译tslib,版本为tslib1.4.tar.gz。对其环境变量进行设置并配置相关的库,在配置环境变量时,最好建立一个sh脚本,每次使用qt前运行脚本来设置环境变量,避免不同版本带来的冲突,方便不同环境时进行切换。接着,将宿主机生成lib下的库文件下载到目标机上,将 PC 机上/usr/local/Trolltech/QtEmbedded-4.6.3-arm/lib 中的库复制到目标机的 /usr/local/Trolltech/QtEmbedded-4.6.3-arm/lib(对应目录复制)上;将 PC 机上 /usr/local/tslib 中的库复制到目标机的 /usr/local上。至此开发环境建立完成。

2.2 控制界面的设计

准备工作顺利完成以后,就可以进行开发嵌入式GUI程序了。Qt/Embedded主要开发流程如图2所示。

Qt/Embedded编程既可以图形化编程也可以传统的代码编程,二者各有优劣,笔者采用二者相结合的方式编程:通过派生自QWidget的QMainWindow的子类化来实现主窗口的创建;图形的绘制是由子类化的QGraphicsPolygonItem来完成实现;工作区通过QGraphicsScene的子类化来完成,利用Qt所特有的信号和槽机制来实现响应相应的鼠标事件等。进入主窗口可以看到工具栏、菜单栏及工作区等,从功能上可分为3个单元:数据处理单元、数据显示单元和数据传输单元。数据处理单元包括3个模块:算数模块、逻辑模块和控制模块,其中算数模块用于实现数据运算,包括加、减、乘、除等数据运算;逻辑模块用于实现与、或、非、异或等逻辑控制功能;控制模块用于实现PID算法控制功能。用户可以将控制模块进行组态配置,完成数据运算、数据比较及控制算法等复杂的控制功能。数据显示单元主控制器将采集、控制的数据都存储在SQLite数据库中,该单元通过调用数据库的数据,可以实时显示各个通道的运行情况、控制方法及数据变化等,同时也可以查看历史数据,方便用户对现场的分析。数据传输单元主要是完成数据的无线发送,即GPRS模块,该模块是将处理后的数据或历史记录发送至上位机或者服务器,可以实现用户的远程在线实时访问,从而可以使该控制器做到无人值守。在控制界面中,有相应的功能供用户选择,同时可以对模块进行参数设置,完成数据的发送与接收功能。用户界面运行如图3所示。

2.3 程序的发布

将开发好的程序通过交叉编译工具编译成ARM可执行文件,再通过ARM目标板终端的rz命令将可执行文件下载到根文件系统的某个目录下,设置好相应的环境变量,便可以运行程序。为了给用户提供友好的人机界面,把程序再添加到QPE中,如果必要的话,还可以把程序设置成开机自启动,只要把程序的名字和路径添加到启动时的执行文件里即可。

3 结束语

笔者提出了一种基于ARM9的小型通用智能控制器的通用控制界面的设计方法,该GUI 通过跨平台由Qt/Embedded所开发,可移植性和可扩展性好,采用模块化设计,灵活性好,实时性高,能够满足人机交互的需求。

参考文献

[1]孙昌青.基于Qt_Embedded的嵌入式GUI系统的研究与构建[D].武汉:湖北工业大学,2009.

[2]孙天泽,袁文菊.嵌入式设计及Linux驱动开发指南——基于ARM9处理器[M].第2版.北京:电子工业出版社,2007.

[3]吴坤.基于S3C2440的平动式啮合电机驱动控制系统设计[D].北京:北京邮电大学,2010.

[4]吴晓云.基于ARMg和GPRS的电力负控管理系统的设计与实现[D].西安:长安大学,2010.

[5]孙鹤旭,林涛.嵌入式控制系统[M].北京:清华大学出版社,2006.

[6]Blanchette J,Summerfield M著,闫锋欣译.C++GUIQt 4编程[M].第2版.北京:电子工业出版社,2008.

嵌入式Qt 篇2

由于嵌入式系统的特殊性,它一般不会建立在庞大的操作系统以及GUI之上,如Windows或X Windows,它对实时性的要求非常高,对GUI的要求更高。

1 嵌入式Linux GUI概述

目前,以Linux为操作系统的嵌入式系统中,常用的GUI有Qt/Embedded、MicroWindows、MiniGUI及OpenGUI等。

1.1 Qt/Embedded

Qt/Embedded是挪威的奇趣科技(TrollTech)公司(注: 该公司已于2008年2月被诺基亚公司以1.53亿美元收购)推出的一个跨平台的C++图形用户开发界面库。它的主要特点是界面美观、色彩配比好,使用与Qt/Windows和Qt/X11完全一样的API接口,许多基于Qt的程序可以非常方便地移植到嵌入式系统中;同时,它具有丰富的模块,用户可以根据需要选择它的特性集合。

1.2 MicroWindows

MicroWindows是由美国CenturySoftware 公司开发的开放源码的嵌入式GUI项目。它不需要其他图形系统的支持,可以充分利用Linux提供的FrameBuffer机制来进行图形显示。同时在底层提供了对多种芯片的支持,基本上用C语言实现,因此移植性较好。

1.3 MiniGUI

当然,我们国家的MiniGUI也是一个比较成熟的图形用户界面系统,面向基于Linux的实时嵌入式系统,使用现有成熟的图形引擎(SV2GALib/LibGGI),采用类似Win32的线程机制,集成了多字体和多字符集,支持硬件加速能力,充分利用显示内存。

1.4 OpenGUI

OpenGUI在Linux上存在很长时间了。这个库是用C++编写,提供C++接口。OpenGUI支持鼠标和键盘事件,在Linux上与Qt/Embedded一样,都是基于FrameBuffer实现绘图。但OpenGUI基于汇编实现内核并利用MMX指令进行了优化,因此运行速度快,从而影响了它的可移植性。

2 嵌入式Linux GUI 软硬件环境

2.1 硬件环境

本文的嵌入式系统是针对三星公司的S3C2410,它集成ARM920T内核,采用0.18微米CMOS工艺,并在ARM核基础上集成了丰富的外围接口,如图1所示。

主要功能:1个MMU(实现Linux内核的虚拟内存管理)、4个DMA通道、1个LCD控制器(结合DMA实现Linux内核的mmap()系统调用)、3个UART、2个SPI、2个USB主设备端口、1个看门狗、4个PWM定时器、117个I/O端口、24个外部中断源、8路10位ADC以及触摸屏接口、外部扩展存储器控制器(达1G,足够Linux内核与上层软件使用)等[1]。

外围器件的扩展和电路板的设计主要由硬件工程师完成,不是本文的主要讨论范围,在此只是阐述嵌入式Linux GUI的硬件环境。

2.2 软件环境

在完成开发板的设计制作之后,在其上运行GUI程序之前,必须要有一定的底层软件环境。如下:

1) 采用宿主机/目标机的开发模式,在宿主机上搭建交叉编译环境[2]

2) ViVi(Linux的引导程序)的移植

ViVi是三星公司专门为S3C2410加载Linux内核。

3) Linux内核移植和文件系统的制作

内核的移植比较复杂,这也是采用Linux的繁琐之处。移植采用2.4.x的内核源码,针对相应的硬件平台(S3C2410),修改部分体系结构相关的源码,主要是汇编语言部分,添加相应的驱动(FB“帧缓冲”驱动程序、鼠标、键盘类设备驱动程序等),再裁剪内核,去掉无关选项,将配置好的内核交叉编译后,生成映像文件,烧写到开发板的flash中。文件系统采用jffs2,通过busybox制作Linux需要的命令,建立基本目录和设备文件等,最后通过mkfs.jffs2工具生成映像文件,烧写到flash中[3]。

3 Qt/Embedded图形引擎的实现

Qt/Embedded图形引擎基于FrameBuffer,FrameBuffer是在Linux 2.2版本以后推出的标准显示设备驱动接口,采用mmap()系统调用,可将它的显示缓存映射为可连续访问的一段内存指针[4]。FrameBuffer的驱动包括两个方面:一是LCD的初始化(ARM9中集成了LCD控制模块)。二是对画面缓冲区的读写,如read、write和lseek的系统调用。而将画面缓冲区的内容输出到LCD上,则由硬件自动完成。DMA通道和画面缓冲区设置完成后,DMA开始正常工作,并将缓冲区的内容不断发送到LCD上。这个过程是基于DMA对LCD的不断刷性。基于该特性,FrameBuffer驱动程序必须将画面缓冲区的存储空间重新映射到一个不加高缓存和写缓存的虚拟地址空间中,这样才能保证应用程序通过mmap()系统调用将该缓存映射到用户空间后,该画面缓存的写操作能够实时地体现到LCD上。

Qt/Embedded中,Qscreen类为抽象出的底层显示设备基类,其中声明了对于显示设备的基本描述和操作方式。另一个重要的基类是QGfx类,它抽象出对于显示设备的具体操作接口,如选择画线、画矩形和alpha操作等。这两个基类是Qt/Embedded图形引擎的底层抽象。其中具体函数基本都是虚函数,Qt/Embedded对具体的显示设备,如Linux FrameBuffer、Qt Virtual FrameBuffer 做的抽象接口类全都由此继承并重载基类中的虚函数来实现。图2给出了Qt/Embedded中图形引擎实现的结构框图。

Qt/Embedded用QLinuxFbScreen来处理FB设备,针对具体显示硬件(如Mach卡和Voodoo卡)的加速特性,Qt/Embedded从QLinuxFbScreen和图形设备环境模板类QGfxRaster类继承出子类,并针对相应硬件重载相关虚函数。

4 Qt/Embedded和Qtopia的移植

4.1 在宿主机上搭建Qt/Embedded环境

本过程需要qt-x11.2.3.2.tar.gz、e2fsprogs-1.37.tar.gz、qt-embedded-2.3.7.tar.gz、tmake-1.13.tar.gz、qtopia-free-1.7.0.tar.gz等软件包。qt-x11.2.3.2.tar.gz 提供uic、qvfb、designer等开发工具;e2fsprogs-1.37.tar.gz 提供uuid头文件和libuuid.a;qt-Embedded-2.3.7.tar.gz主要提供libqte.so;tmake-1.13.tar.gz生成和管理Makefile;qtopia-free-1.7.0.tar.gz实现应用程序的桌面。

由于Qt/Embedded和Qt/X11有一样的API,所以我们在开发嵌入式环境的应用程序时,可以先在宿主机上开发,利用强大的qvfb工具模拟嵌入式的GUI运行环境,通过调试后,再经过重新编译,移植到开发板上,这样就不用每次都刷性开发板上的内容,大大提高了开发GUI的速度。

进入宿主机kde的图形化界面,打开终端,进入root用户模式。将上述软件包拷贝到自己的目录下的qte目录,用vi编辑器建立build安装脚本(设置QTDIR、QPEDIR、TMAKEDIR、TMAKEPATH、PATH等环境变量,通过./configure-help命令分别配置各个软件包的Makefile文件)。有几步需要注意,cp-r ../e2fsprogs-1.37/lib/uuid ./qtopia/include和cp ../e2fsprogs-1.37/lib/libuuid.a ./qtopia/lib帮助Qtopia建立时所需要的头文件库文件,如果不加,在编译qtopia时会找不到libuuid.a,编译出错;在编译qt-embedded时,根据./configure –help配置qt/embedded库,比如加入对jpeg、gif的选项,当然,如果选择它们,将增强应用程序的功能,但也增加了qt/embedded库的大小。

运行build脚本./build,根据宿主机的处理速度不同,该安装脚本运行时间会有长短,本人用1G内存的宿主机,大概四十几分钟即可完成。安装完成之后,就可以开发嵌入式GUI程序了,先来测试一下,在终端下输入qvfb[5]&,让它在后台运行,然后执行qpe –qws,即可看到qtopia的运行界面,如图3所示。

4.2 Qt/Embedded 编程核心

在宿主机上建立好开发环境后,就可以在上面开发应用程序了,开发后的程序先在qvfb上运行调试,通过之后,再移植到开发板上,方便快捷。

Qt/Embedded软件体系结构如图4所示。该图比较了Qt/Embedded和X11的体系结构。Qt/Embedded摒弃了X lib库,采用帧缓冲(FrameBuffer)作为底层图形接口。同时将外部输入设备抽象为键盘和鼠标事件。Qt/Embedded底层图形接口采用mmap()系统调用,将显示设备抽象为帧缓冲,从而应用程序可以直接写内核FrameBuffer,避免了使用繁琐的X lib/Server机制,这正是资源相对紧张的嵌入式系统所需要的。

Signals/Slots是Qt编程的基础,也是核心,如果没有它,就失去了Qt的活力。

Signals/Slots是对象间通信的手段,它不同于传统的回调函数,增加了应用程序的可靠性和安全性。当某个对象的状态发生改变的时候,它发出信号,让另一个或者多个对象的插槽接收,尽管它并不知道哪些函数定义了插槽,而插槽也不知道要怎样接收。Signals/Slots真正实现了封装的概念,信号与插槽不必一一对应[6]。

下面是一个简单的信号与插槽的部分代码示例:

QApplication app(argc,argv);

QPushButton quit("click me",0);

quit.resize(100,30);

quit.setFont(QFont("Times",18,QFont::Bold));

QObject::connect(&quit,SIGNAL(clicked()),&app,SLOT(quit()));

app.setMainWidget(&quit);

quit.show();

return app.exec();

QApplication类负责应用程序的控制流和主要设置,它包括系统设置函数(如fontMetrics())、事件处理函数(如exec())、文本处理(如translate())、高级光标处理(如overrideCursor())等,处理和调度所有来自窗口系统和其他资源的事件,管理程序的开始和结束。

QObject类是所有能够处理信号、插槽和事件的Qt对象的基类,能够创建带有父对象及其名字的对象,对象的父对象可以看作该对象的所有者。

QObject::connect(&quit,SIGNAL(clicked()),&app,SLOT(quit()))实现了quit对象和app对象的通信,只要前者一产生clicked信号,后者马上作出响应。

编译上述代码,输出clickme可执行文件,在qvfb模拟环境下,有两种方式执行它。方法一,启动qvfb,在命令行中直接输入./clickme –qws,即可看到单个clickme应用程序在qvfb中运行,点击按钮,立即退出;方法二,将该应用程序加到Qtopia桌面环境下运行,在执行clickme之前,在$QPEDIR/apps/Applications目录下新建clickme.desktop文件,编辑该文件:

[Desktop Entry]

Comment=A click Program

Exec=clickme

Icon=

Type=Application

Name=clickme

Name[no]=Klokke

Name[de]=Uhr

然后把可执行文件clickme拷贝到$QPEDIR/bin下,在后台启动qvfb,运行qpe –qws,这是在Qtopia界面上就能看到clickme应用程序图标,运行之,如图5所示,应用程序界面上出现了clickme图标,点击它即可运行。

4.3 开发板上的移植

交叉编译Qt/Embedded,方法同宿主机上编译类似,将编译器换成arm-linux-gcc,修改qt-2.3.7/configs/linux-arm-g++-shared文件,将其中的相应行改为:

SYSCONF_CXX=/home/bull/2.95.3/bin/arm-linux-g++;SYSCONF_CC=/home/bull/2.95.3/bin/arm-linux-gcc;SYSCONF_LINK=/home/bull/2.95.3/bin/arm-linux-gcc;SYSCONF_LINK_SHLIB=/home/bull/2.95.3/bin/arm-linux-gcc;SYSCONF_AR=/home/bull/2.95.3/bin/arm-linux-ar。

至此,可以编写Qt应用程序,在宿主机上通过qvfb模拟嵌入式环境下运行,调试通过后,方便地移植到开发板上,做到“一次编写,多次编译”。

5 结 语

本文针对嵌入式Linux GUI,介绍了目前流行的几种GUI,阐述了各自的特点说明了嵌入式GUI的软硬件环境,然后着重研究了Qt/Embedded 图形引擎的实现,并通过对该库的裁剪配置,使其尽可能精简,以适应嵌入式系统资源有限的束缚,最后通过一个实例,测试移植效果。Qtopia作为一款成功的嵌入式GUI桌面环境,是PDA、消费电子等嵌入式产品的优秀解决方案,本文通过实例说明了它的良好性能。

参考文献

[1]三星.S3C2410数据手册(arm920T)[M].2003.

[2]Karim,Yaghmour.Building Embedded Linux Systems[M].O'Reilly,2003.

[3]周绪宏,梁阿磊,戚正伟.基于嵌入式Linux的智能手机系统软件的设计与实现[J].计算机应用与软件,2008,25(3):60-61.

[4]W Richard Stevens,Stephen A Rago.Advanced Programming in theUNIX Environment:Second Edition[M].Addison Wesley Professional,2005.

[5]谭大鹏,李培玉,潘晓弘.基于Qt/E的嵌入式工业监测轻型图形用户界面构件库开发[J].计算机集成制造系统,2009,15(2):401.

嵌入式Qt 篇3

随着半导体技术的不断发展,嵌入式系统得到了越来越广泛的应用。在嵌入式系统的开发中,越来越多的软件开发工作集中在图形用户接口(GUI)上[1]。Qt/Embedded是一个专门为嵌入式系统设计图形用户界面的工具包,由挪威TrollTech公司开发。Qt/Embedded为C++构架,直接基于Linux中的Frame Buffer,可以运行在被Linux系统支持的多种不同的处理器体系上,例如:Intel X86,ARM,MIPS,PowerPC等。Qt/Embedded在小型化、低功耗、便携式的嵌入式系统中得到了广泛的应用。

使用Qt/Embedded开发应用程序时,开发者一般需要从QWidget、QDialog、QScrollView等类继承以实现用户窗口。而经常困扰开发者的是用户窗口的闪烁问题。本文将介绍Qt/Embedded的绘图机制,分析产生闪烁的原因并给出无闪烁绘图的方法。

2 Qt/Embedded绘图机制

在Qt/Embedded中使用QPainter类创建用户图形。QPainter可以在一个“绘图设备”上进行绘制图形,例如窗口或者位图等[2]。为了避免干扰Qt/Embedded自己的画图功能,使用QPainter创建用户图形时需要将画图代码放在paintEvent()的画图事件函数中,并且用QPainter::begin()和QPainter::end()函数来启动和停止画图。QPainter类提供了低级的画图函数,例如画线,画矩形等。QPainter类还提供了许多函数用来在实际绘图之前设置绘图样式,例如使用QPainter::setPen()函数设置画笔的样式,使用QPainter::setBrush()函数设置填充样式等。在许多情况下,系统会自动产生一个绘图事件,并且paintEvent()被调用,例如一个窗口第一次显示或者大小被调整等。开发者也可以通过调用QWidget::repaint()或QWidget::update()来强制产生一个绘图事件,从而调用paintEvent()来实现用户图形的刷新。repaint()和update()两个函数的区别在于,前者会产生一个立刻的重新绘制,而后者只是向Qt主事件回路中插入一个绘图事件,等待Qt下一个主事件回路执行。连续调用update()时,Qt会将多个绘图事件优化为一个绘图事件以避免闪烁。调用repai(bool erase),如果erase为TRUE,Qt在paintEvent()调用之前先擦除绘图区域;否则不擦除。

3 闪烁的原因分析

当Qt产生一个绘图事件来刷新图形时,Qt首先用背景颜色来擦除绘图区域,然后在背景上绘制图形。这种分两步绘图的方法是很方便的,这样开发者就可以简单地在窗口上绘制需要的图形而不用关心其他的像素。但这种分两步绘图的方法也是产生闪烁的主要原因。这种刷新方法给人的视觉感受是,先看到擦除绘图区域之后的背景颜色,然后看到背景上的绘图,这之间有一个短暂的时间差。如果这样的刷新频繁发生,人眼就能感受到明显的闪烁。

许多情况下,Qt会产生绘图事件,例如移动重叠的窗口,新显现的窗口部分需要重绘;调整窗口的大小;程序调用update()或者repaint()等。每当窗口的大小改变时,系统就会产生一个绘图事件,刷新背景然后重新绘制所有图形,从而导致闪烁。如果窗口大小改变,窗口中的内容也随之改变,则称窗口内容为“动态的”;如果窗口大小改变,其内容不改变,则称之为“静态的”。例如常用的文字处理工具,窗口内容与窗口大小无关,并不随着窗口大小的改变而改变。这种情况下,既然原有的可见部分并不改变,就没有必要重新绘制,而只需绘制新显示的部分。因此通过QWidget::setWFlags()将窗口部件标记设置为WStaticContents可以避免闪烁。

对于那些窗口内容与窗口大小相互独立的窗口,可以通过设置窗口部件标记为WStaticContents来避免闪烁,但这类窗口毕竟是少数。下面介绍两种更为常用和有效的方法来避免闪烁,即部分刷新和双缓冲技术。

4 无闪烁绘图方法

不管窗口内容是静态的还是动态的,许多情况下我们还是要重新绘制窗口的一部分,而这些绘图仍然可能导致闪烁。Qt刷新时先用背景色填充背景,然后绘图事件负责绘制用户图形。如果绘图事件比较慢,例如绘图之前要先进行大量的计算,那么绘制背景和绘制用户图形之间的延迟就比较大,从而导致闪烁;延迟越大,闪烁就越明显。解决问题的根本方法就是我们自己负责擦除背景,并尽可能地减少擦除背景和绘图之间的时间差。

通过QWidget::setWFlags()将窗口部件标记设置为WRepaintNoErase或WResizeNoErase,或者调用repaint(FALSE),可以让Qt在绘图之前不擦除背景。

4.1 部分刷新

程序员自己负责背景的刷新,就可以在擦除背景和绘制图形之前做必要的计算,而不是在擦除背景和绘制图形之间进行计算,从而避免了闪烁。但这样做仍然存在一个问题。

例如如下的绘图:绘制整个背景,绘制线条1,绘制线条2,绘制线条3,…,绘制线条n。设绘制一条线条的时间为t,那么绘制整个背景和绘制线条1之间的延迟就是1×t,这个延迟是很小的,所以当绘制线条1时基本上没有闪烁。而绘制整个背景和绘制线条n之间的延迟为n×t,如果n很大,这个延迟就比1×t大多了,有可能造成闪烁。

解决这一问题的方法是部分刷新,简而言之,就是先绘制部分背景,然后绘制相应部分的图形,再绘制部分背景,接着绘制相应部分的图形,如此反复。如此将背景分为多个部分,然后部分刷新,而不是一下子绘制整个背景。应用到上述例子中,绘图操作为:绘制线条1的背景,绘制线条1,绘制线条2的背景,绘制线条2,…,绘制线条n的背景,绘制线条n,绘制剩余背景。这就使得绘制线条与绘制相应背景的延迟为固定的1×t,可以明显地减少闪烁。需要注意的是,使用部分刷新,需要独立地绘制剩余背景,因为绘制的线条可能没有覆盖整个窗口。

当绘制部分图形的时间t比较短时,部分刷新可以很好地解决闪烁问题。但是如果绘制部分图形的时间t比较长,可能仍会造成闪烁。解决这一问题的方法是将用户图形分解成适当小的部分,每次只刷新很小的部分,但这种方法有时会很复杂,导致编程的难度很大。一个更好的解决方法是双缓冲技术。

4.2 双缓冲技术

双缓冲技术就是在内存中开辟一块缓冲区,将这块缓冲区看作一幅位图,先用背景色填充这幅位图,然后在这幅位图上绘制用户图形,最后将这幅位图显示到窗口中。这样绘制背景和绘制图形之间就没有延迟,可以完全避免闪烁。使用双缓冲技术的简便方法是,先用QPixmap制作一幅位图pixmap,该幅位图与需要刷新的矩形区域大小一致,然后用pixmap.fill()填充位图的背景色,接着用QPainter p(&pixmap)申请一个指向该位图的画笔,并在这幅位图上绘制用户图形,最后用bitBlt()或者p.drawPixmap()将这幅位图填充到窗口。

双缓冲技术可以完全消除闪烁,但是以内存消耗和时间开销为代价。例如,在每一个绘图事件中需要分配(宽×高×位深)比特的内存空间,如果系统使用640×480液晶显示器,位深为16-bpp(每个像素16比特),那么需要分配的内存空间就是680×480×16比特,即600K字节。虽然可以重复利用分配的内存空间以减少分配内存的时间开销,但分配的内存应该为可能需要刷新区域的最大值,内存消耗比较多。解决这一问题的有效方法是将部分刷新和双缓存技术结合起来使用。例如分配线条大小的内存空间作为位图,而不是整个窗口大小,然后在位图上绘制线条的背景和线条,接着复制这幅位图到相应的线条位置。这样需要分配的内存大小为(线条宽度×线条高度×位深)比特,远小于整个窗口所需内存。

需要注意的是,使用双缓冲技术时应该禁止Qt在绘图事件之前擦除背景,可以调用repaint(FALSE)产生绘图事件。

5 直接访问帧缓冲

双缓冲技术可以完全消除闪烁,但其内存消耗和时间开销比较大。尤其对于嵌入式实时系统,双缓冲的时间开销有时无法满足实时性要求。下面讨论一种直接访问帧缓冲的方法,并运用部分刷新,实现快速无闪烁画图。

5.1 帧缓冲

帧缓冲(Frame Buffer)是在Linux内核架构版本2.2以后推出的标准显示设备驱动接口,是显存抽象后的一种设备。帧缓冲设备对应的设备文件为/dev/fb*,而/dev/fb为当前缺省的帧缓冲设备,通常指向/dev/fb0。

帧缓冲设备驱动模块运行在所谓的内核空间里,而应用程序运行在所谓的用户空间中[3]。帧缓冲允许上层应用程序不用关心显存的工作细节而直接对显示缓冲区进行读写操作,写操作可以立即反映在LCD屏上。Frame Buffer的显示缓冲区位于Linux中的内核空间,用户程序需要通过mmap()函数将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址,之后用户程序就可以通过读写这段虚拟地址访问屏幕缓冲区。直接访问帧缓冲,对显示缓冲区进行写操作,是一种最快的显示方式。

5.2 QDir2 QDirectPainter类

Qt/Embedded直接基于Linux中的Frame Buffer。QDirectPainter类继承自QPainter类,提供了直接访问帧缓冲的方法,该类仅可在Qt/Embedded中使用[4]。QDirectPainter类的uchar*frameBuffer()函数返回指向屏幕缓冲区首地址的指针,int depth()const函数返回显示的位深,int width()const函数和int height()const函数分别返回显示的宽度和高度。例如系统使用640×480液晶显示器,位深为16-bpp(每个像素16比特),则由QDirectPainter类获得的位深为16,宽为640,高为480。

由QDirectPainter类uchar*frameBuffer()函数获得指向屏幕缓冲区首地址的指针后,就可以直接对屏幕缓冲区进行写操作,并立即反映到LCD屏上。设LCD屏上坐标为(x,y)的像素点表示该点到LCD屏左方水平距离为x,到LCD屏上方垂直距离为y;系统的位深为16-bpp,且R:G:B为5:6:5,即一个16位数据的高五位表示红色,中间六位表示绿色,低五位表示蓝色。将坐标为(x,y)的像素点刷新为某一颜色的操作就是:*(fb+width*y+x)=color;其中fb为指向屏幕缓冲区首地址的指针,由于位深为16-bpp,所以fb为指向unsigned short int型的指针;width为屏幕宽度;color为表示颜色的16位无符号数据。这就是直接访问帧缓冲的画点函数。有了画点函数后,就可以编写出画线,画矩形等其他函数。

5.3 快速无闪烁画图

笔者参与的某项目使用640×480的LCD屏,位深为16-bpp;系统在每20ms内响应一帧数据,绘图区域为620×400。需要实时绘制的图形为检测的回波波形和刻度线等,如图2所示。由于20ms的实时性要求和绘图区域比较大,使用QPainter直接画图虽然可以满足实时性要求,但有明显的闪烁;使用双缓冲画图,可以消除闪烁,但时间远大于20ms,无法满足实时性要求。

为了快速无闪烁画图,笔者采用了直接访问帧缓冲和部分刷新。直接访问帧缓冲可以获得最快的画图速度,但也要自己负责绘图区域每个像素点的刷新。为了避免闪烁,实时刷新函数在绘制完一帧图形后,将其数据保存。当另一帧数据到达时,先用上一帧数据部分刷新背景,然后部分绘制新一帧图形,即只刷新上一帧图形的某一列,然后用新一帧数据绘制该一列,如此反复。使用直接访问帧缓冲和部分刷新,虽然增加了一些编程复杂度,但可以满足系统的实时性要求并避免闪烁。经过实际测试,系统运行良好,实时绘图时间小于13ms,满足实时性要求,且没有闪烁。

6 结束语

在嵌入式系统的开发中,软件开发工作主要集中在图形用户接口上。Qt/Embedded以其丰富的类库,完善的功能和良好的接口在嵌入式系统中得到了广泛的应用。在Qt/Embedded应用程序开发过程中,经常困扰开发者的是用户窗口的闪烁问题。本文介绍了Qt/Embedded的绘图机制,分析了绘图时产生闪烁的原因,并给出无闪烁绘图的方法。

在嵌入式系统中,系统通常有实时性要求。为了满足实时性要求,必须提高绘图速度。本文讨论了一种利用QDirectPainter类直接访问帧缓冲的绘图方法,并利用部分刷新,实现快速无闪烁绘图。

摘要:首先对Qt/Embedded的绘图机制进行了介绍,然后分析了绘图时产生闪烁的原因,给出无闪烁绘图的方法。为了提高绘图速度,对一种利用QDirectPainter直接访问帧缓冲的绘图方法进行了讨论,实现了快速无闪烁绘图。

关键词:Qt/Embedded,无闪烁,双缓冲,QDirectPainter,嵌入式Linux

参考文献

[1]孙天泽,袁文菊,张海峰.嵌入式设计及Linux驱动开发指南――基于ARM9处理器[M].北京:电子工业出版社,2005.

[2]Blanchette J,Summerfield M.C++GUI Programming with Qt3[M].Prentice Hall PTR,2004.

[3]Corbet J,Rubini A,Hartman G K.Linux Device Drivers[M].3rd ed.南京:东南大学出版社,2005.

[4]Qt参考文档[EB/OL].http://www.qiliang.net/qt/index.html.

嵌入式Qt 篇4

仪表作为汽车整个系统中十分重要的部分, 是提高汽车综合性能的重要方面之一。随着计算机软硬件技术、总线技术、电子技术等的快速发展, 控制系统臃肿、接线布线复杂、占用空间大的传统电磁机械仪表渐渐被淘汰, 虚拟仪表正以传统机械仪表无法比拟的速度迅猛发展[1]。目前虚拟仪表通常包括纯数字仪表和虚拟仪表盘仪表2种:纯数字仪表成本较低, 但功能和界面比较简单, 满足不了一般驾驶员的需求;而现有的虚拟仪表盘仪表虽然功能和界面比较丰富, 但又存在着开发成本高、可移植性和可重绘性差、可扩展性不足等缺点, 不利于大范围的推广与应用[2,3]。

针对传统仪表和现有仪表存在的不足, 本文提出了一种新型的车载虚拟仪表设计方案, 采用ARM处理器S3C6410为核心的硬件平台和以嵌入式Linux系统为核心的软件平台, 并在此基础上采用开放源代码的图形界面库QT开发仪表终端应用程序。该虚拟仪表可读性好, 读数精度高, 在可移植性、可维护性和成本方面都得到了良好的改善, 具有较大的科研价值和商业使用价值。

1 系统总体设计

本文所介绍的车载虚拟仪表的基本设计思想是将汽车上安装的各种传感器采集到的数据进行智能化的处理, 然后在运行于嵌入式Linux系统的使用QT设计的虚拟仪表盘上进行显示, 以便于监测汽车各系统的工作状况, 如剩余油量、当前车速、行驶里程等, 并在某状态出现异常或存在危险时向驾驶员提示报警。

如图1所示, 本车载虚拟仪表系统的设计总体由3个部分组成:

(1) 信号采集:对汽车上安装的的各种传感器采集的速度、剩余油量等汽车状态信息, 经过处理转换后, 将其转换为计算机可以识别的数字量;

(2) 数据处理:将“信号采集”过程传输来的数据进行必要的处理, 将有用的数据保存, 以便于显示和报警, 本过程主要由嵌入式处理器完成;

(3) 人机交互:将“数据处理”过程处理完成的数据, 在使用QT设计的虚拟仪表盘上动态显示, 主要显示内容有:当前速度、燃油箱的存油量、时间日期、行驶里程、报警灯等;在某项状态出现异常时, 通过报警模块向驾驶员提示报警。

2 虚拟仪表硬件设计

虚拟仪表的硬件结构图如图2所示。虚拟仪表的核心处理器采用ARM1176JZF-S核的S3C6410芯片, 其主频最高可达到667 MHz, 内部继承了强大的多媒体处理单元, 带有3D图形硬件加速器, 并支持2D图形图像的平滑缩放等操作, 有利于为用户提供高灵敏度的汽车状态动态显示;外接256 MB SDRAM和2 GB NANDFLASH;串口连接信号转换处理模块, 转换处理模块内部集成CAN-RS232转换器及24位的A/D转换器LTC2414, 接收相关传感器采集的各种汽车状态信号, 并经过处理后, 将处理完成的数据上传至处理器;外接LCD模块采用8寸TFT液晶显示屏, 处理器内部集成的LCD控制器信号线经过驱动电路后即可连接LCD模块, 为虚拟仪表显示提供了硬件平台;外接由语音芯片组成的报警模块, 在必要的时候可以由处理器驱动报警模块以语音的形式向驾驶员提示报警。

3 虚拟仪表软件设计

本系统采用嵌入式Linux作为操作系统, 在Linux平台下编写虚拟仪表的驱动程序和应用程序, 采用QT/embedded设计虚拟仪表软面板。应用程序的主要功能有, 当接收到各个经转换处理的传感器采集到的信号后, 将其有用的数据提取并加以存储, 然后调用仪表显示程序, 将需要显示的内容显示到不同的虚拟仪表盘中, 同时并行判断各项参数是否正常, 若出现异常则调用语音报警程序和显示程序提示报警。虚拟仪表软件结构图如图3所示。虚拟仪表软件开发主要有2个内容:开发环境的搭建、虚拟仪表应用程序的设计[4]。

3.1 开发环境的搭建

为了开发满足功能的应用程序, 本文采用的软件开发环境是Vmware WorkStation 7虚拟机和Fedora 13操作系统, 在此环境中安装交叉编译器ARM-linux-gcc 4.5.1, 用来完成包含相关驱动程序的虚拟仪表系统内核、QT库和应用程序的编译;编译安装QT/Embedded库, 用来支持虚拟仪表人机交互界面程序的开发并生成虚拟仪表系统中需要的QT库文件;编译Tslib触摸屏库, 为虚拟仪表系统添加触摸屏支持;在Fedora13系统中安装QT Creator软件, 用于完成虚拟仪表系统应用程序的开发;移植嵌入式设备的系统引导程序U-boot;编写硬件平台相关驱动[5], 然后裁剪编译Linux2.6.10内核并在其中加载已编译的相关驱动[6];制作硬件平台需要的根文件系统, 在其中移植已配置、编译过的tslib库和QT/Embedded库[7]。

3.2 应用程序开发

本虚拟仪表系统的的应用程序基于QT/Embedded平台, 使用QT的轻量级集成开发环境QT Creator完成开发, 最后在已搭建的开发环境中编译生成可执行二进制文件, 并将其移植到硬件平台中的文件系统中进行测试。

虚拟仪表系统应用程序的主要工作流程如图4所示, 在系统上电后, 应用程序开始运行, 要实现汽车虚拟仪表系统的功能, 应用程序需要完成虚拟仪表面板和后台处理程序的开发:

3.2.1 虚拟仪表面板的绘制

虚拟仪表面板主要将汽车的一些基本状态在LCD上通过表盘和数字直观、动态的显示出来, 本设计中采用速度、油量、电池电量、时间日期、安全带、安全气囊、行驶里程等状态。

为了提高本虚拟仪表的可扩展性和可维护性, 在本设计中, 为每种具体的虚拟仪表对象定义一个抽象类。下面即以仪表盘类 (QMeter) 为例介绍本系统中虚拟仪器面板的绘制。

在需要显示的各种状态中, 速度和油量通常以仪表盘形式显示, 虚拟仪表模块中的虚拟仪表盘采用QT的二维图形引擎的基础类QPainter开发。QPainter具有丰富的图形图像绘制函数, 并支持反走样、渐变填充、像素混合、线性变换等特性, 利用这些函数完成仪表盘的绘制[8,9]。

3.2.2 后台处理程序

后台处理程序主要将系统下层采集的数据进行分析处理, 将有用的数据传送至虚拟仪表面板显示, 实现虚拟仪表的动态显示, 同时以多线程的方式不断检测汽车各项状态, 当某项状态出现异常或存在危险时驱动LCD和语音芯片向驾驶员报警[10], 其中异常状态有超速、存油量过低、电池电量过低等。下面以报警子程序为例讲解后台处理子程序。

报警子程序在后台处理程序中新建一个线程, 通过多线程的方式以轮询的方式查询各个传感器的状态, 当发现某个状态存在危险时, 驱动语音芯片发出相应的报警信息。其定义如下:

QT特有的信号与槽 (signal/slots) 机制实现方式如下:

connect (m_thread, SIGNAL (sendData () ) , this, SLOT (Deal () ) ) ;

通过调用QObject对象的connect函数, 将报警线程的sendData信号与主线程的槽函数Deal () 关联, 当报警侦听线程发射信号时, 主线程槽函数及时被调用, 驱动报警。

4 应用程序示例

将裁剪、编译过的内核与制作的带QT库的文件系统烧写到开发板。在开发环境内交叉编译编写的应用程序, 得到可执行二进制文件, 将此文件移植到开发板, 即可实现应用程序的发布。重新开机, 运行应用程序即显示虚拟仪表界面, 如图5所示。

通过汽车上的各种传感器采集数据, 通过控制器和高速CAN总线传送到S3C6410硬件平台解析, 应用程序得到解析后的数据后, 即可动态的显示当前车辆的各种状态及报警情况。

5 结语

本文设计的汽车虚拟仪表, 具有优良的跨平台性能;该设计方案使得仪表信息量增大, 操作简单, 易于维护, 界面友好;采用开放源码设计, 使得本系统开发成本降低;使用双缓冲技术消除了仪表显示页面的闪烁;采用多线程技术, 使处理、显示与报警同时进行, 提高了系统的实时性与灵敏度;将具体的虚拟仪表对象定义为抽象类, 增强了虚拟仪表的扩展性。经实验测试, 本虚拟仪表系统的所有功能模块均能正常运行, 该系统的应用将对降低汽车的成本, 缩短汽车仪表系统的研发周期提供高友好度的人机界面具有重要的意义

摘要:为了简化汽车内部控制系统, 降低汽车制造成本, 提高人车交互界面的友好度, 设计并实现了一种新型的汽车虚拟仪表。采用以ARM处理器S3C6410为核心的硬件平台和以嵌入式Linux系统为核心的软件平台, 并在此基础上采用开放源代码的图形界面库QT开发仪表终端应用程序。经试验验证, 虚拟仪表系统具有成本较低、界面友好、反应灵敏等特点, 并在跨平台性、可扩展性等方面得到了显著改善。

关键词:汽车,虚拟仪表,嵌入式Linux,QT,ARM

参考文献

[1]陈丽, 陈焱焱.基于VC++6.0的虚拟汽车数字仪表盘的设计[J].电脑开发与应用, 2009, 22 (8) :29-31.

[2]涂天佳, 王见, 秦树人.跨平台的虚拟仪器开发研究与实现[J].中国测试, 2010, 36 (5) :55-58.

[3]程兴亚.基于嵌入式系统的虚拟仪器设计[J].微计算机信息, 2004, 12 (20) :63-65.

[4]胡志文, 张崎.基于嵌入式Linux的自助点菜终端设计[J].现代电子技术, 2011, 34 (4) :14-16.

[5]CORBET J, RUBINI A, KROAH-HARTMAN G.Linux设备驱动程序[M].北京:中国电力出版社, 2005.

[6]BOVET P D, CESATI M.深入理解Linux内核[M].北京:中国电力出版社, 2007.

[7]韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社, 2008.

[8]BLANCHETTE Jasmin, SUMMERFIELD Mark.C++GUIQT4编程[M].北京:电子工业出版社, 2008.

[9]蔡志明, 卢传富, 李立夏.精通QT4编程[M].北京:电子工业出版社, 2008.

[10]李青松, 周晓光, 周慧玲.基于QT的工程机械监控和诊断系统的设计与实现[J].计算机与信息技术, 2011, 13 (12) :3-5.

[11]石春虎, 曲红星, 陈雷.直升机虚拟仪表DLL设计与实现[J].电子科技, 2011 (5) :104-107.

嵌入式Qt 篇5

随着计算机与视频技术的发展,人们已经可以用摄像装置拍摄自己感兴趣的图像并保存、传输,比如在家庭、办公室、停车场等场所安装的视频监控系统。这些场所安装的监控系统一般要求成本低廉、具有视频存储和传输功能。使用嵌入式系统,可以实现上述目的。不过当前的很多嵌入式视频监控系统是基于GSPCA[1]的系统。GSPCA是法国人编写的Linux视频驱动程序包,支持不少摄像头,也提供了像Spacview之类的视频录制与传输程序。但基于GSPCA软件包构建的监控系统有以下缺陷:首先,GSPCA的图像必须先经过网络传到PC机上才能显示的,如果在嵌入式系统的显示屏上本身反而不能直接显示;第二,GSPCA的图像处理功能并不丰富,不能提供移动检测等功能;第三,GSPCA的图像格式只有MJPEG形式,等于每帧图像都要存储;这样的存储量过大,而如果使用MPEG格式,由于使用帧间压缩,可以节省大量存储空间;第四,缺乏移动侦测功能,因为通常视频如果完全存储下来即便使用MPEG格式也会占据很大的存储空间;如果加入了移动检测功能,在检测到物体运动后再存储视频,就可以大大节省视频文件占据的存储容量;第五,GSPCA所提供的操作界面基本是自己编写的,非常简陋,较之主流的图形化界面库而言,缺乏对于后续开发的良好支撑,这一点严重阻碍了基于GSPCA产品的商业应用。另外,还有以下几点:首先,随着触摸屏技术的快速发展,目前触摸屏的成本已经很低,完全可以把触摸屏应用于监控系统的启动、管理和关闭,这样可以非常方便使用者。其次,如果用户不在现场,此监控系统还应该具备把视频文件通过网络发送给用户的能力。综上所述,在充分考虑后,基于嵌入式技术,开发出了一种成本适中、使用触摸屏、具有视频存储、移动检测和传输功能的视频监控系统。该系统可以独立应用于家庭中的实时监控,也可以用于办公室、车场或和其他大型监控系统集成以执行大范围的监控任务。

1 总体结构

监控系统由数字摄像设备和视频监控终端组成。结构如图1所示。数字摄像设备提供原始图像数据,视频监控终端对图像数据进行处理,数字摄像设备与视频监控终端的视频数据接口相连。监控终端包括管理模块、录制与检测模块、显示模块、触摸屏模块、通信模块。其中管理模块具备系统管理功能,例如报警级别的设置;录制与检测模块完成图像数据压缩、视频录制、差异检测与报警任务;显示模块显示当前实拍的图像或按照不同速率播放录制的视频;触摸屏模块提供触摸输入并传递给管理模块、录制与检测模块和显示模块的功能;通信模块可通过有线或无线方式传输报警信号和视频文件,可以加密传输的数据。

本系统由软件和硬件部分构成。硬件部分由TQ2440开发板和USB摄像头构成。其中TQ2440开发板[2]上包括基于ARM9体系的s3c2410/2440CPU、32 MB内存、32 MB闪存、320×240点阵彩色液晶触摸屏、USB口和以太网口。USB摄像头为中星微ZC301摄像头,支持常见的V4L协议。软件部分包括linux操作系统(内核2.6)、Qt4图形中间件、OpenCV2.0库和自主开发的监控软件。Linux操作系统(内核2.6)具备强大的多进程处理能力、出色的稳定性和良好的扩展性,易于安装各种应用软件和函数库。Qt4图形中间件具有丰富的图形化工具库,OpenCV2.0有强大的图像处理能力。图2为软件系统的架构图。

2 管理模块设计及实现

管理模块功能包含了摄像启动、播放启动、系统设置和系统退出功能。下图为管理界面。管理模块的开发主要是基于Qt4进行的。Qt是一个多平台的C++图形用户界面应用程序框架,属于诺基亚,现在发展到Qt4[3]。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的因此很容易扩展,并且允许真正的组件编程。自从1996年早些时候Qt进入商业领域,它已经成为全世界范围内数千种成功的应用程序的基础,Qt不仅是流行的Linux[4]桌面环境KDE的基础,近年来越来越多的智能化仪表[5]、虚拟仪表[6]也开始采用Qt作为基本的图形化操作界面。

管理模块的主要工作流程是这样的:用户开启系统后即进入主控菜单;在菜单中,选择播放视频、修改设置或摄像;如果是摄像,实时采集图像并提示用户选择图像保存方式究竟是比较节约空间的移动检测方式还是常规方式;用户选择后开始录制;当系统检测到物体移动时将保存当前图像;系统通过网络发送出图像文件;系统结束录制,返回主控菜单;如果是播放,打开当前目录,用户可挑选需要查看的视频文件;选中视频文件后开始播放视频,用户可选择播放视频的速度;系统结束播放,返回主控菜单;如果是修改设置,则调整所需的系统属性,例如背景图案;保存修改的系统属性到设置文件里;设置结束,返回主控菜单;用户关闭系统退出。

管理模块的主要流程如图3所示。

管理模块的部分代码如下:

3 录制与检测模块设计及实现

录制与检测模块功能分成按常规拍摄和移动侦测拍摄两种。后一种拍摄条件的每秒帧数低于常规拍摄,主要是考虑一些用户可能希望长时间监视某个区域,这时若使用常规节奏拍摄就要耗费大量存储空间,而使用移动侦测可大大节省存储空间。

该模块使用了OpenCV函数库,OpenCV[7]是开放源代码的计算机视觉类库,由英特尔公司位于俄罗斯的研究实验室所开发,它是可免费获得的由一些C函数和C++类所组成的库,用来实现常用的图像处理及计算机视觉算法,已广泛运用于人脸识别[8]、目标运动检测[9]、图像处理[10]等领域。选用它有两个原因:首先,OpenCV的图像处理功能相当强大,不仅能处理图像的格式、提供了提供移动检测等功能;其次,OpenCV产生的视频文件可以根据需要选择MPEG4,MJPEG等多种压缩格式,从压缩机理上看,MPEG4算法由于采用插值与帧间预测,不需要压缩每帧图像,压缩效果显然好得多。综合上述因素,选用了OpenCV。

模块接收来自摄像头的图像数据。本模块启动后会调用函数cvCreateCameraCapture检测摄像头是否连接,如果检测到摄像头则得到一个指针,否则会报错退出。之后的工作流程是:先调用cvQueryFrame操作此指针,再调用函数cvCreateVideoWriter指定视频压缩格式并获得视频文件指针。这样可得到一个视频缓冲区A,然后该缓冲区接收从USB摄像头提取的图像数据,如果没有移动检测,则该缓冲区的数据将按照选定的视频压缩格式以调用函数cvWriteFrame的方式被写入视频文件。如果有移动检测,则调用函数motionDetect。该函数的功能如下:将A缓冲区的数据被保存到另外的缓冲区B里等待比较操作,A缓冲区继续接收来自摄像头的数据,A与B的数据在经过相关二值化和降噪处理后进行比较,如果比较中发现数据的不同之处已经超过预设的门限值,则把拍摄时间叠加入B缓冲区的视频数据。此处的视频数据记录以调用cvWriteFrame的方式被写入本地视频文件。本地视频文件的命名是按照数字升序自动产生的,因此不会覆盖之前拍摄的视频。操作过程如图4所示。

录制与检测模块的部分代码如下:

此外,当前后帧差异检测的结果达到或超过了预设的报警门限,不仅可录入到本地视频文件,还可发出报警信号;同时还会将画面再记录入一个很短的临时视频文件中(例如长度为10 s),并将这个临时视频文件连同报警信号提交给通信模块。该临时视频文件在记录时每幅图像都可加入年-月-日-时-分-秒格式的时间戳。临时视频文件的长度可以预先设置,该文件在传输后即被删除以节省装置的存储空间。采用这种方式出于3种考虑:首先,自动发出的报警信息可以满足迅速报警的需要,随后发出的短长度临时视频文件可以提供具体的现场图像信息;其次,上述数据量较之在网络上传输整个的视频文件可明显降低通信带宽,节省运行成本;最后,由于传输的过程耗时短,数据被截获的概率低,安全性也有所提高。当用户从管理界面选择了录制功能后,屏幕上将全屏显示出当前采集的图像。并在屏幕的偏下位置显示出一组半透明的按钮:“录像”、“返回”和“节约/正常”。这是考虑到用户可能需要随时调整拍摄模式或停止摄像、暂停录制:点按了“录像”按钮后液晶屏上的图像会被记录入视频文件;点按“返回”后会中止录制返回上级菜单;点按“节约”按钮之后,系统仅仅在记录到物体移动时才记录视频文件,且该按钮上的字符变为“正常”,这时若再点按该按钮,系统将按照常规速度记录视频文件,不再根据是否有物体移动记录视频。图5为录制与检测模块工作时的界面显示。

4 显示模块设计及实现

显示模块有两种工作模式:一种是本地实时监视模式;另一种是视频回放模式。在本地监视模式下,本模块启动后也会检测与摄像头是否连接,如果没有检测到摄像头则会报错退出。检测通过后,来自摄像头的图像被实时显示在彩色液晶屏上。而且操作界面设计成使用户可以在观看监视画面的同时能够随时开始录制视频文件或结束录制,录制视频期间液晶屏实时显示的内容不受录制操作的任何影响。在视频回放模式下,用户可以在图形化菜单中选择以前记录的视频文件并播放,播放的画面显示在液晶屏上,播放时可以根据用户需要随时调整播放速度的快慢,也可以随时暂停播放。

显示模块综合使用了Qt4和OpenCV的库函数。播放过程如下:通过Qt4提供的文件接口函数在制定路径下找到要播放的视频文件。在打开视频文件前先开辟一个内存缓冲区C,将读出的视频数据写入到此缓冲区内。通过在PaintEvent函数中调用函数drawImage将时间戳等字符数据写入到视频缓冲区C内,这一步是实现在Qt4界面内显示图像所必须的步骤。在这一步中还可以根据需要叠加控制按钮到显示画面中。然后C缓冲区的合成视频数据再写入到操作系统的帧缓冲区内,过程如图6所示。在Qt中设置好每秒写入帧缓冲区25帧画面,用户就可以从液晶屏上看到连续运动的图像了。实时显示的过程与播放过程很相似,不同之处是图像数据的来源从视频文件变成了USB摄像头。

打开视频文件及建立缓冲区C的部分代码如下:

5 通信模块设计

通信模块使用了socket函数,通过线程机制独立于其他程序运行。模块分成初始化和传输两部分。在摄像模块分配视频缓冲区之后就初始化通信模块。初始化过程首先以函数pthread_create启动了一个独立的线程,该线程调用cvCreateVideoWriter获取被传输视频文件指针,待函数正确返回指针后再建立socket连接,至此初始化过程结束。当摄像模块检测到物体移动后,调用cvWriteFrame在抓取的帧图像中打上时间戳并将其存储为临时视频文件,随后向远端服务器发送连接请求,连接建立后,通过TCP连接传送该文件。在传输结束后再等待一段时间后删除临时文件;之后释放视频文件指针,释放socket连接,最后注销线程。

通信模块的部分代码如下:

6 结语

经过测试,证明嵌入式家用视频监控系统达到了预期的功能:既可以按照普通速率录制视频并实时显示在液晶屏上,也可以通过移动检测方式,只记录变化较大的图像;可以通过图形化界面,以触摸方式选择实时录制视频或者查看以前录制的视频。在移动检测方式下,可以报警并将图像通过网络发送给远端服务器。

后续的开发包括:加强移动侦测处理能力,做到能够识别某些特征物;加入镜头移动功能,增大监视范围;增添移动互联网接口,利用手机查看视频文件;增加视频记录格式,支持更多文件格式;丰富图形化界面功能,增添报时、对讲、夜光等功能。

摘要:当前有不少视频监控系统是基于GSPCA开发的,它们存在不能在本地显示视频,缺乏移动检测等图像处理功能,对于存储空间要求高,难于升级等缺点。为解决上述问题,结合Qt4和OpenCV开发了一种嵌入式视频监控系统。该系统的硬件环境为ARM9系统,操作系统为Linux。系统不仅能够在本地实时显示监视画面,还能够根据移动检测的结果记录视频,大大节省了存储空间。系统还可以在上述检测中加入与预设报警门限值进行比较的功能,根据比较结果决定是否报警并通过网络将拍摄的图像传递给远端系统。达到了在本地显示视频,节约存储空间,可进行移动检测,便于升级的效果。

关键词:嵌入式视频监控系统,移动检测,Qt,OpenCV

参考文献

[1]Linweig.GSPCA驱动移植介绍[OL].[2010-02-10].http://blog.csdn.net/linweig/article/details/5305334.

[2]广州天嵌计算机科技有限公司.TQ2440开发板使用手册[R].广州:天嵌计算机科技有限公司,2009.

[3]成洁,卢紫毅.Linux窗口程序设计:Qt4精彩实例分析[M].北京:清华大学出版社,2008.

[4]陈莉君.Linux操作系统内核分析[M].北京:人民邮电出版社,2000.

[5]陈卿,戴仙金,唐玉国.基于Qt/Embedded的新生儿监护仪软件系统设计与实现[J].微计算机信息,2012,28(9):431-432.

[6]王润民,赵祥模,惠飞,等.基于嵌入式Linux与QT的汽车虚拟仪表设计[J].现代电子技术,2012,35(6):1-4.

[7]BRADSKI Gary,KAEHLER Adrian.Leanring OpenCV[M].United States:O'Reilly Media,Inc.,2008.

[8]刘静.基于OpenCV机器视觉库的人脸图像预处理方法研究与实现[J].电子设计工程,2012,20(16):186-187.

[9]刘馨,马宏峰,王宏斌.基于OpenCV和DirectShow的交通运动目标检测算法研究[J].华东交通大学学报,2012,29(3):21-25.

嵌入式Qt 篇6

Qt/Embedded是在嵌入式环境下所使用的Qt。目前市面上所有上市的Linux PDA都是采用Qt/Embedded作为图形接口的函数库。Qt/Embedded的特性是可以直接在Framebuffer上显示图形接口, 反应的速度更快, 这对硬件和容量都有限制的嵌入式环境非常重要。

主要介绍QT在基于ARM的嵌入式Linux系统下的移植与应用。

1 Qt/Embedded开发环境介绍

Qt/Embedded应用程序的开发可以在安装了一个跨平台开发工具链的不同的平台上编译。系统采用的是在Linux平台下开发, 在Linux平台下以虚拟缓冲帧的方式来运行, 其实是有一个X11的应用程序虚拟了一个缓冲帧。通过指定显示设备的宽度、高度和颜色深度, 虚拟出来的缓冲帧将和物理的显示设备在每个像素上保持一致。这样每次调试应用时开发人员就不用总是刷新嵌入式设备的FLASH存储空间, 从而加速了应用的编译、链接和运行周期。

运行Qt的虚拟缓冲帧工具的方法是:在Linux的图形模式下运行命令:

qvfb (回车)

当Qt嵌入式的应用程序要把显示结果输出到虚拟缓冲帧时, 我们在命令行运行这个程序时, 在程序名后加上-qws的选项。例如:$>hello-qws

Qt包含了许多支持嵌入式系统开发的工具, 其中一些工具我们会在别的地方介绍。最实用的工具 (除了上面我们提到的虚拟缓冲帧) 有tmake、Qt designer (图形设计器) 、uic和moc。

(1) tmake

tmake是一个为编译Qt/Embedded库和应用而提供的Makefile生成器。它能够根据一个工程文件 (.pro) 产生不同平台下的Makefile文件。

开发者可以使用Qt图形设计器可视化地设计对话框而不需编写一行代码。使用Qt图形设计器的布局管理可以生成具有平滑改变尺寸的对话框, tmake和Qt图形设计器是完全集成在一起的。

(2) Qt designer

Qt Designer是设计窗口组件 (Widget) 的应用程序, 在安装Qt的bin目录下输入./designer命令, 就启动一个包含很多Qt组件的可视化界面。在此组织应用程序的各组建分布很方便, 最后生成一个file.ui和main.cpp文件;file.ui是用XML语言编写的一个文本。

(3) uic (user interface compiler)

uic是从XML文件生成代码的用户界面编译器, 用来将file.ui文件生成file.h和file.cpp文件 (命令如:uic-o file.h file.ui uic-o file.cpp file.ui) , 但生成的这两个文件不是标准的纯C++代码, 通常称为Qt的C++扩展, 因为Qt的对象间运用了信号和插槽的通信机制, 在文件中用Q_OBJECT宏来标识。

(4) moc (元对象编译器)

moc用来解析一个C++文件中的类声明并且生成初始化对象的C++代码, moc在读取C++源文件, 如果发现其中一个或多个类的声明中含有Q_OBJECT宏, 就给出这个使用Q_OBJECT宏的类生成另外一个包含元对象代码的C++元文件;元对象代码对信号插槽机制、运行时的类型信息和动态属性系统是需要的。

2 Qt/Embedded库的移植

2.1 Qt/Embedded开发环境的安装[1]

一般来说, 嵌入式应用程序都是先在装有Linux操作系统的PC机或工作站来完成Qt/Embedded的开发, 然后再把应用程序交叉编译后发布到嵌入式Linux系统下。在一台装有Linux操作系统的机器上建立Qt/Embedded开发环境, 需要三个软件安装包:tmake工具安装包, Qt/Embedded安装包, Qt的X11版安装包。

由于上述软件安装包有许多不同版本, 要注意版本不同可能导致的冲突。Qt for X11安装包的版本要比Qt/Embedded的版本旧。因为Qt for X11安装包的两个工具uic和designer产生的源文件会和Qt/Embedded的库一起被编译链接, 本着“向前兼容”的原则, Qt for X11的版本应比Qt/Embedded的版本旧。本系统采用的是tmake 1.11;Qt/Embedded 2.3.7;Qt 2.3.2 for X11。

2.1.1 安装tmake

在Linux命令模式下运行以下命令:

2.1.2 安装Qt/Embedded 2.3.7

在Linux命令模式下运行以下命令:

上述命令./configure-qconfig-qvfb-depths4, 8, 16, 32指定Qt嵌入式开发包生成虚拟缓冲帧工具qvfb, 并支持4, 8, 16, 32位的显示颜色深度。另外我们也可以在configure的参数中添加-system-jpeg和gif, 使Qt/Embedded平台能够支持jpeg、gif格式的图形。

2.1.3 安装Qt/X11 2.3.2

在Linux命令模式下运行以下命令:

根据开发者本身的开发环境, 可以在configure的参数中添加别的参数, 比如, -noopengl或-no-xfs, 可以通过输入./configure-help来获得一些帮助信息。

2.2 交叉编译Qt/Embedded的库[2,3]

Qt/Embedded应用程序最终是要在嵌入式Linux系统下运行, 所以要把Qt嵌入式应用程序编译成支持在开发板上运行的目标代码之前, 需要两样东西, 一是基于目标板的交叉编译器, 另一个是交叉编译后的Qt/Embedded库。

2.2.1 安装交叉编译工具

交叉编译是指一个处理器平台上编译产生一个工程代码的另一个处理器的目标代码。通过下载并修改toolchain作为交叉编译工具, 要求最好使用cross-3.3.2及其以后的版本, 这样才能对Qt/Embedded有良好支持。

2.2.2 交叉编译Qt/Embedded库

当有了ARM的linux编译器后, 就可以使用这个编译器进行交叉编译Qt/Embedded库的源代码, 从而产生一个以ARM为目标代码的Qt/Embedded库。具体过程如下:

(1) 解压Qt/Embedded

在Linux命令模式下运行如下命令:

(2) 配置Qt/Embedded的安装

#.cp/配置文件所在路径/qconfig-local.h.

Qt/Embedded的安装选项有很多个, 可以直接输入“”来运行配置。Qt/Embedded的安装选项还允许自己定制一个配置文件, 来有选择的编译Qt/Embedded库, 这个安装选项是“-qconfig local”;当指定这个选项时, Qt/Embedded库中安装过程会寻找qt-2.3.7/src/tools/qconfig-local.h这个文件来编译链接Qt/Embedded库。在定制中添加了对触摸屏显示的支持。

2.3 Qt/Embedded支持触摸屏显示[4,5]

Qt/Embedded 2.x系列中, 触摸屏设备和键盘设备需要根据具体的驱动程序接口中Qt/Embedded中设备实现对应的设备操作类。其中对应于鼠标类设备的实现位于src/kernel/qwsmouse_qws.cpp中。

在文件qwsmouse_qws.cpp中添加对触摸屏的支持。具体修改如下:

(1) 定义和Linux内核文件driver/input/tsdev.c中数据结构ts_event相一致的TS_EVENT数据结构, 定义如下:

(2) 修改校准文件的位置

在函数void QCalibrated Mouse Handler::write Calibration () 和

read Calibration () 中修改如下:

(3) 对打开的设备文件进行修改

在函数QTPanel Handler Private::QTPanel Handler Private中, 修改如下:

(4) 由于内核TS_EVENT结构中, 当触摸屏按下时对pressure的设置为1, 因此在void QTPanel Handler Private::read Mouse Data () 函数中把

修改为:

2.4 移植Qt/Embedded库

在ARM板的根文件系统的tmp目录下创建新目录qt, 在qt目录下创建新目录lib。把交叉编译后生成的Qt/Embedded库拷贝到ARM板上的根文件系统下的/tmp/qt/lib目录下。在使用QT库之前要设置环境变量。命令如下:

这样Qt/Embedded应用程序就可以在ARM板上移植了。

3 Qt/Embedded应用程序的开发

开发一个Qt应用程序的流程如下[6]:

3.1 生成一个工程文件 (.pro文件)

一个应用通常对应一个工程文件, 生成一个工程文件, 并对它做一些简单的编辑, 然后使用一个专门的工具 (例如tmake) 处理这个工程文件, 就可以生成一个Makefile文件。

产生一个工程文件的其中一个方法是使用progen命令 (progen程序可以在tmake的安装路径下找到) 。下面是使用progen产生一个名为hello的工程文件的命令:

产生的hello.pro工程文件并不完整, 开发者还需手动往里添加工程所包含的头文件, 源文件等信息。

3.2 新建一个窗体

在qt-2.3.2的安装路径的bin目录下运行“./designer”命令, 就启动了一个Qt图形编辑器。点击编辑器的“new”菜单, 弹出了一个“new Form”对话框, 在这个对话框里我们选择“Widget”, 然后点击“OK”按钮, 这样我们就新建了一个窗体。接着, 我们可以对这个窗体进行设置。

设置完成后, 将其保存为hello.ui文件, 这个文件就是project窗体的界面存储文件。

3.3 生成窗体类的头文件和实现文件

界面文件使用uic工具产生出窗体类的头文件和实现文件, 例如hello.ui节目文件产生hello窗体类的头文件和实现文件, 具体方法如下:

这样我们就得到hello窗体类的头文件hello.h和实现文件hello.cpp。接下来根据我们要实现的具体功能, 在hello.cpp文件里添加相应的代码。

3.4 编写主函数main ()

一个Qt/Embedded应用程序应该包含一个主函数, 主函数所在的文件名是main.cpp。主函数是应用程序执行的入口点。

3.5 编辑工程文件

在工程文件中添加窗体类的头文件、实现文件和主函数文件。

3.6 生成Makefile文件

编译器是根据Makefile文件内容来进行编译的, 所以需要生成Makefile文件。Qt提供的tmake工具可以帮助我们从一个工程文件 (.pro文件) 中产生Makefile文件。从工程文件生成一个Makefile文件的具体做法如下:

把环境变量$TMAKEPATH所指的目录设置为arm编译器的配置目录, 把当前QTDIR环境变量指向Qt/Embedded的安装路径, 这样就可以使用tmake来生成Makefile文件。

#export TMAKEPATH=/tmake安装路径/

当前目录生成的Makefile文件, 需要进行一些修改, 具体修改如下:

将LINK=arm-linux-gcc改为LINK=arm-linux-g++

3.7 编译链接整个工程

在命令行下输入make命令对整个工程进行编译链接。

这样make生成的二进制文件就可以在ARM上允许了。

4 实验结果

实现了简单的qt应用程序, 主要有按钮和标签, 点击按钮display就会在标签上显示“Hello World!”, 点击按钮clear就会清空标签。应用程序首先在pc上调试通过后, 再重新交叉编译后移植到ARM板上。

下图是该qt应用程序在pc上运行的结果。

下图是该应用程序在嵌入式ARM板上运行后在LCD上显示的结果。

结束语:对Qt/Embedded提供的开发工具进行分析, 同时叙述了Qt/Embedded在pc上的安装和在嵌入式ARM板上的移植。同时通过一个简单的应用程序对Qt/Embedded应用程序的开发流程进行了详细介绍。

摘要:QT是一个用于多种平台图形界面程序开发的C++工具包。同时QT还包含了一些工具使得编写程序变得又快又直接。QT的跨平台能力和国际化支持保证了QT应用程序占有尽可能广阔的市场。Qt/Embedded是面向嵌入式系统的QT版本。主要讲述Qt/Embedded库中基于ARM的嵌入式Linux系统下的移植, 同时使用一个简单的应用程序来说明Qt/Embedded应用程序的开发流程。

关键词:QT,Qt/Embedded,交叉编译,ARM

参考文献

[1]Jasmin Blanchette, Mark Summerfield.C++GUI Programming with Qt3[M].Prentice Hall in association with Trolltech Press.2004.

[2]张方辉, 王建群.Qt/Embedded在嵌入式Linux上的移植[J].计算机技术与发展, 2006 (7) :64-67.

[3]王存健, 张建正.嵌入式Linux下Qt/Embedded的应用[J].计算机技术与发展, 200 (611) :179-181.

[4]李春萍, 李颉思.嵌入式Linux中对触摸屏驱动的设计[J].计算机工程与设计, 2007 (6) :1387-1389.

[5]畅卫功, 丁忠林.嵌入式Linux系统中触摸屏驱动的研究[J].微计算机信息, 2007 (1-2) :103-105.

嵌入式Qt 篇7

随着嵌入式处理器运算能力的不断提高, 对外设支持的不断丰富, 嵌入式Linux系统的应用也逐渐增多。与其它GUI相比, QT/E可以直接访问底层设备, 速度非常快, 使得QT/E成为用于运行基于QT的程序的最紧凑环境, 很适合高端的手持设备和移动设备[2]。但由于它没有分层, 使其结构层次欠佳, 软件代码维护不便, 因此, 需要对其进行优化。

1 QT/E的客户/服务器结构分析

在KDE桌面系统中, KDE通过X Window的客户/服务器 (以下简称C/S) 系统完成显示和设备的输入工作。对于嵌入式设备来说, 系统内存小且CPU速度相对较慢, 故嵌入式设备的桌面系统不可能建立在X Window之上[3], 因此, QT/E给出了自己的C/S模型, 并提供了类似X Window的功能, 完成显示和设备的输入工作。QT/E的C/S结构如图2所示。

QT/E中的服务器的功能主要包括:接收鼠标、键盘、触摸屏等外部设备产生的事件, 并把事件分配给对应的客户机处理;协调客户机之间的行为。客户机功能主要是根据服务器发送来的鼠标、键盘等外设事件进行具体处理, 将处理结果以图形方式表示出来 (如窗口的缩放、移动等) 。QT/E的服务器功能主要由QWSServer类来实现, 客户机的功能主要由QWSDisplay类来实现[4]。

QT/E中的C/S结构分为两种情况: (1) 当服务器端与客户在同一个进程中, QT/E在服务器端启动的同时, 系统会自动启动一个客户端, 并生成一个client对象保持与这个客户端的通讯, 当服务器端有消息发送给客户端则把此消息放到与服务器对应的消息队列 (outgoing) 中, 待客户端处理时从服务器消息队列取出消息, 把消息放入到客户端消息队列中;当客户端有消息发给服务器端时, 则把此消息放到与客户端对应的消息队列 (incoming) 中, 待服务器端处理时从客户端消息队列取出消息, 把消息放入到服务器端消息队列中; (2) 当服务器端和客户端在不同的进程中, 客户/服务器间的通信通过socket文件描述符csocket进行。服务器将来自鼠标及键盘等硬件输入的数据通过QWSClient:sendEvent () socket以事件形式发送给客户端, 另外还把服务器对窗口的全局管理方面的事件发送给客户端。每启动一个客户端服务器端都会创建一个特定定义 (QWSClient类描述) 的对象与客户端对应, 这个对象会构造一个与客户端对应的套接字 (socket) , 当有消息发送给客户端时, 服务器找到这个特定对象, 把消息写到这个对象中构造的套接字中, 这样客户端通过系统调用select () 能发现有消息到来, 从而激发函数到本进程中的socket中去读。同理, 客户端将一些需要服务器处理的窗口管理及鼠标键盘命令数据通过socket以事件形式发送给服务器。同时, 客户端还通过socket接收来自服务器的事件, 分发给客户端相关的窗口进行处理。

QT/E的C/S模型被封装在QT/E内核中, 通过QAPPlication建立模型的各种关系, 用QT/E类库完成与模型的各种通信及操作。对于应用程序开发者来说, 开发QT/E应用程序与开发PC机的Qt应用程序基本上是一样的, 几乎感觉不到QT/E的C/S模型的存在。

2 QT/E进程间通讯方式分析

在QT/E中, 进程内的通讯可以通过信号与槽, 其内封装了回调函数, 而进程间的通讯是通过通道, 通道通讯底层同样是封装了socket机制, 所以通道通讯同样是socket通讯[5]。在应用系统中, 服务器端保存着一个QCopServerMap队列, 里面存放的是通道名和对这个通道感兴趣的客户端对象的索引, 在客户端保存着一个QCopClientMap队列, 里面存放着通道名和对这个通道感兴趣的对象。客户端间在使用通道通讯前必须先在服务器端进行通道注册。具体过程是需要通讯的进程先构造一个QCopChannel对象, 把这个对象与要注册的通道名字放入到QCopClientMap队列中, 然后向服务器端发送注册命令, 服务器端在接到消息后读出注册命令, 找到与这个客户端相对应的客户端对象, 然后把这个通道名和这个客户端对象的索引加入到QCopServerMap中。当客户端需要与其它客户端通讯时, 客户端把本身所属通道的名字与消息数据一起发送到服务器端, 服务器端判断是通道信息就调用相关函数处理, 其过程是先在QCopServerMap中找到这个通道名, 取出其对应的客户端对象列表, 再把这个消息通过循环调用相应的发送函数发给所有注册了此通道名的客户端对象, 最后通过socket机制发送到客户端。C/S通讯关系如图3所示。

3 QT/E的C/S结构的优化方案

通过以上分析, 可知QT/E的服务器不是独立运行的, 而是附加在客户端应用程序上, 服务器端本身也具有客户端的功能。在QT/E的内核中, 客户和服务器的代码在上层基本上是在一个函数中处理, 只是用一些变量来标识是否是服务器用的代码, 程序在编写时必须把服务器端与客户端功能的代码都包含在一起, 因此就要用大量的条件判断进行区别, 结果造成代码可读性较差, 不便修改和维护。

通过把QT/E中服务器的功能与客户端的功能在代码上分离, 使服务器启动时不启动客户端, 以-qws启动的进程只作为服务器端, 仅在系统中起协调作用, 这样可使软件结构更加清晰合理, 此时客户端只有一种情况, 从而可以省去很多不必要的判断和一些为服务器端启动的特定的消息队列等。

服务器端与客户端在底层只通过socket通讯, 从而在服务器端与客户端的消息处理循环中减少了大量的判断与不必要的函数调用, 不仅增强了程序的可读性, 也方便了程序的移植和维护。同时, 由于减少了一些不必要的函数调用以及对QT/E中大量的线形函数的优化, 系统运行速度和效率也会有所提高。

4 结束语

QT是KDE等项目使用的GUI支持库, 所以其可移植性非常好, 许多基于QT的Xwindow程序可以非常方便地移植到嵌入式系统。自从QT/E以GPL条款发布以来, 就有大量的嵌入式Linux开发商转到了QT/E系统上, QT/E作为Linux系统上主要的图形引擎将在以后得到更为广泛的应用。因此, 对QT/E的内核结构进行进一步分析与优化是非常必要的。

参考文献

[1]倪继利.QT及linux操作系统窗口设计[M].北京:电子工业出版社, 2006.

[2]Prentice Hall Ptr.C++GUI Programming with Qt4[M].2版.齐亮, 译.北京:北京航空航天大学出版社, 2008.

[3]纪君峰.基于QT/E的嵌入式系统研究及应用[M].北京邮电大学, 2008.

[4]trolltech公司QT/E源代码4.0.1[Z/OL].http://www.trolltech.com/download/tech previews.html.

上一篇:公路电影下一篇:非财务效益分析