©2006Embedded图形界面Qt程序设计牛建伟邹琪嵌入式系统课程——实验五©2006Embedded•实验目的•实验内容•Qt介绍•Qt编程特点•实验步骤©2006Embedded实验目的•了解在Linux下安装Qt以及Qt/Embedded的基本步骤•学会在Qt/E平台下使用Virtualframebuffer显示程序结果©2006Embedded实验内容•在Linux系统的宿主PC下,编译和使用Qt/E平台•在Qt/E平台下编译和运行一个程序使用Virtualframebuffer显示运行结果©2006EmbeddedQt简介•Qt是Trolltech公司的标志性产品,是一个跨平台的C++图形用户界面(GUI)工具包•Qt应用程序接口与工具兼容于所有支持平台,让开发员们掌握一个应用程序接口,便可执行与平台非相关的应用开发与配置Qt/Windows(WindowsXP,2000,NT4,Me/98)Qt/Mac(MacOSX)Qt/X11(Linux,Solaris,HP-UX,IRIX,AIX等)•Qt对不同平台的专门API进行了专门的封装(文件处理,网络等)©2006EmbeddedQt特征(1)•面向对象Qt具有模块设计和注重软件构件或元素的可重用行的特点•构件支持Qt提供信号(signal)和插槽(slot)概念,这是一种类型安全的方法,它允许回调,并支持对象之间在彼此不知道对方信息的情况下进行合作,这使得Qt非常适合于真正的构件编程•友好的联机帮助Qt提供了大量的联机参考文档,有超文本HTML方式,也有Unix帮助页man手册页和补充说明。并且对于初学者,其中的指南将一步步介绍如何进行Qt编程©2006EmbeddedQt特征(2)•便利性由于Qt是一种跨平台的GUI工具包,它对编程者隐藏了在处理不同窗口系统时潜在的问题,Qt定义了一些类来隐藏在不同操作系统上不同处理方式下的细节问题•用户自定义使用其他的一些工具包经常会遇到这样一种情况,没有真正适合需求的组件,声称自定义的组件对用户来说就像一个黑匣子。而在Qt中生成用户自定义的组件非常简单,而且易于修改组件的行为•国际化Qt为本地化应用提供了完全的支持,所有用户界面文本都可以基于消息翻译表被翻译成各国语言,Qt还支持双字节16bit国际字符标准©2006EmbeddedQt特征(3)•丰富的API函数Qt为专业应用提供了大量的函数,在Qt的API中含有大约250个C++类,大多数的类都是GUI专有的•可用户化外观Qt支持主题,基于Qt的应用程序能够在Windows外观、Motif外观,以及其它一些用户化外观主题之间切换•完整的一套组件工具Qt编程的基本模块称之为组件,组件是用户界面的组成部分,Qt含有用来创建专业外观的用户界面所需要的所有组件©2006EmbeddedQt编程特点•1.初始化在Qt应用程序中,首先要创建一个QApplication对象,QApplication类负责图形用户界面应用程序的控制流和主设置,在main.cpp中定义如下:intmain(intargc,char**argv){QApplicationa(argc,argv);……}©2006Embedded•1.初始化QApplication包含在main()函数的事件循环体中,对所有来自Window系统和其它源文件的事件进行处理和调度,还包括处理应用程序的初始化和结束,并且提供会话管理。在Qt应用程序中,不管有多少个窗口,QApplication对象只能有一个,而且必须在其他对象之前创建。QApplication类中封装了很多函数,其中包括:系统设置:setFont()用来设置字体事件处理:sendEvent()用来发送事件GUI风格:setStyles()设置图形用户界面的风格颜色使用:colorSpec()用来返回颜色文件文本处理:translate()用来处理文本信息创建组件:setmainWidget()用来设置窗口的主组件……©2006Embedded•2.窗口的创建在Qt程序中,创建窗口比较简单,只要在main.cpp文件中为ApplicationWindow建立一个指针:ApplicationWindow*mw=newApplicatonWindow();ApplicationWindow是在Application.h中定义的类,它是一个QmainWindow的继承类•3.组件的创建组件的创建需要调用相应组件的类,并在头文件中包含此类的头文件或者创建自定义类,继承以后组件类的功能#include“qpushbutton.h”classhello::publicQwidget{……}©2006Embedded•3.组件的创建hello类继承了Qwidget类的特征,并加入了自定义的特征功能,同样需要在头文件中包含此类的头文件在main.cpp的函数中需要创建hello类的实例,或创建QPushButton类的实例,才可以使用helloh(string);QPushButtonhello(“Hello,world!”,0);如果组件本身可以作为主窗口,则无需设置主窗口。在上例中,下压按钮创建时其构造函数中的第二个参数为0,表示按钮所在窗口为主窗口,不需要设置主窗口。否则需要调用QWidget成员函数setMainWidget()来进行设置h.setMainWidget(&h);组件创建时一般是不可见的,这样的好处在于避免大量组件创建时造成的屏幕闪烁现象,要使组件可见需要调用QWidget类的成员函数show()来显示组件h.show();©2006Embedded•4.事件在X程序中,敲击键盘,鼠标指针在窗口中的移动或鼠标按键动作等,都是事件在Xt中提供了提供了一种叫做回调的事件处理方式。它通过翻译表,将事件映射为相应的动作,当组件得到事件通知,就去表中找出相应的动作例程进行处理。这种机制需要应用程序注册有关组件的回调函数或普通的事件处理函数,以分发循环Xt的事件Qt事件的处理过程:QApplication的事件循环体从事件队列中拾取本地窗口系统事件或其他事件,译成QEvent(),并送给QObject::event(),最后送给QWidget::event()分别对事件处理其实在Qt程序中,事件处理的方式也是回调,但与以往所不同的是,事件的发出和接收采用了信号(signal)和插槽(slot)机制,无须调用翻译表。利用信号和插槽进行对象间的通信是Qt的最主要特征之一。©2006Embedded•4.事件当对象状态发生改变的时候,发出signal通知所有的slot接收signal,尽管它并不知道哪些函数定义了slot,而slot也同样不知道要接收怎样的signalsignal和slot机制真正实现了封装的概念,slot除了接收signal之外和其它的成员函数没有什么不同,而且signal和slot之间也不是一一对应©2006EmbeddedSignal和Slot的声明(1)•在Qt程序设计中,凡是包含signal和slot的类中都要加上Q_OBJECT的定义,下面的例子给出了如何在一个类中定义signal和slot:classStudent:publicQObject{Q_OBJECTpublic:Student(){myMark=0;}intmark()const{returnmyMark;}publicslots:voidsetMark(intnewMark);signals:voidmarkChanged(intnewMark);private:intmyMark;};©2006EmbeddedSignal和Slot的声明(2)•signal的发出一般在事件的处理函数中,利用emit发出signal,在下面的例子中在在事件处理结束后发出signalvoidStudent::setMark(intnewMark){if(newMark!=myMark){myMark=newMark;emitmarkChanged(myMark);}}©2006EmbeddedSignal和Slot的连接(1)•在signal和slot声明以后,需要使用connect()函数将它们连接起来。connect()函数属于QObject类的成员函数,它能够连接signal和slot,也可以用来连接signal和signal•函数原形如下:boolconnect(constQObject*sender,constchar*signal,constchar*member)const•其中第一个和第三个参数分别指出signal和slot是属于那个对象或组件©2006EmbeddedSignal和Slot的连接(2)•在使用connect()函数进行来接的时候,还需要用到SIGNAL()和SLOT()这两个宏,使用方法如下:QLabel*label=newQLabel;QScrollBar*scroll=newQScrollBar;QObject::connect(scroll,SIGNAL(valueChanged(int)),label,SLOT(setNum(int)));©2006EmbeddedSignal和Slot的连接方式(1)©2006EmbeddedSignal和Slot的连接方式(2)•同一个信号连接多个插槽connect(slider,SIGNAL(valueChanged(int)),spinBox,SLOT(setValue(int)));connect(slider,SIGNAL(valueChanged(int)),this,SLOT(updateStatusBarIndicator(int)));•多个信号连接到同一个插槽connect(lcd,SIGNAL(overflow()),this,SLOT(handleMathError()));connect(calculator,SIGNAL(divisionByZero()),this,SLOT(handleMathError()));©2006EmbeddedSignal和Slot的连接方式(3)•一个信号连接到另一个信号connect(lineEdit,SIGNAL(textChanged(constQString&)),this,SIGNAL(updateRecord(constQString&)));•取消一个连接disconnect(lcd,SIGNAL(overflow()),this,SLOT(handleMathError()));•取消一个连接不是很常用,因为Qt会在一个对象被删除后自动取消这个对象所包含的所有的连接©2006Embedded退出事件程序•退出事件程序,只需要在程序结束时返回一个exec(),例如:returna.exec();•其中a为QApplication的实例,当调用exec()将进入主事件的循环中,直到exit()被调用或主窗口部件被销毁©2006Embedded整个Qt程序的执行过程©2006Embedded实验步骤(1)•arm-linux-gcc-3.4.1.tar.bz2编译qt/embedded环境和相关程序必须使用3.X版本的arm-linux-gcc来进行交叉编译。•安装arm-linux-gcc-3.4.1–从ftp或者光盘资料中得到arm-linux-gcc-3.4.1.tar.bz2•从@192.168.1.54下载到/root–在root的主目录里面解压;•[minjun@localhost~]$tarjxfarm-linux-gcc-3.4.1.tar.bz2-C/–设置环境变量•将arm-linux-gcc的路径加入PATH中,更改当前用户的.bashrc文件,在该文件中增加一行脚本:exportPATH=/usr/local/arm/3.4.1/bin:$PATH•使环境变量立即生