《嵌入式系统实验——实验五-IBMHRLtemplat.pptx》由会员分享,可在线阅读,更多相关《嵌入式系统实验——实验五-IBMHRLtemplat.pptx(42页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 2006 Embedded图形界面图形界面QtQt程序设计程序设计牛建伟邹 琪嵌入式系统课程嵌入式系统课程实验五实验五 2006 Embedded实验目的实验内容Qt介绍Qt编程特点实验步骤 2006 Embedded实验目的实验目的了解在Linux下安装Qt以及Qt/Embedded的基本步骤学会在Qt/E平台下使用Virtual framebuffer显示程序结果 2006 Embedded实验内容实验内容在Linux系统的宿主PC下,编译和使用Qt/E平台在Qt/E平台下编译和运行一个程序使用Virtual framebuffer显示运行结果 2006 EmbeddedQt Qt 简介
2、简介Qt是Trolltech公司的标志性产品,是一个跨平台的C+图形用户界面(GUI)工具包Qt应用程序接口与工具兼容于所有支持平台,让开发员们掌握一个应用程序接口,便可执行与平台非相关的应用开发与配置Qt/Windows(Windows XP,2000,NT 4,Me/98)Qt/Mac(Mac OS X)Qt/X11(Linux,Solaris,HP-UX,IRIX,AIX等)Qt对不同平台的专门API进行了专门的封 装(文件处理,网络等)2006 EmbeddedQt Qt 特征(特征(1 1)面向对象面向对象Qt具有模块设计和注重软件构件或元素的可重用行的特点构件支持构件支持Qt提供信
3、号(signal)和插槽(slot)概念,这是一种类型安全的方法,它允许回调,并支持对象之间在彼此不知道对方信息的情况下进行合作,这使得Qt非常适合于真正的构件编程友好的联机帮助友好的联机帮助Qt提供了大量的联机参考文档,有超文本HTML方式,也有Unix帮助页man手册页和补充说明。并且对于初学者,其中的指南将一步步介绍如何进行Qt编程 2006 EmbeddedQt Qt 特征(特征(2 2)便利性便利性由于Qt是一种跨平台的GUI工具包,它对编程者隐藏了在处理不同窗口系统时潜在的问题,Qt定义了一些类来隐藏在不同操作系统上不同处理方式下的细节问题用户自定义用户自定义使用其他的一些工具包经
4、常会遇到这样一种情况,没有真正适合需求的组件,声称自定义的组件对用户来说就像一个黑匣子。而在Qt中生成用户自定义的组件非常简单,而且易于修改组件的行为国际化国际化Qt为本地化应用提供了完全的支持,所有用户界面文本都可以基于消息翻译表被翻译成各国语言,Qt还支持双字节16bit国际字符标准 2006 EmbeddedQt Qt 特征(特征(3 3)丰富的丰富的APIAPI函数函数Qt为专业应用提供了大量的函数,在Qt的API中含有大约250个C+类,大多数的类都是GUI专有的可用户化外观可用户化外观Qt支持主题,基于Qt的应用程序能够在Windows外观、Motif外观,以及其它一些用户化外观主
5、题之间切换完整的一套组件工具完整的一套组件工具Qt编程的基本模块称之为组件,组件是用户界面的组成部分,Qt含有用来创建专业外观的用户界面所需要的所有组件 2006 EmbeddedQt Qt 编程特点编程特点 1.1.1.1.初始化初始化初始化初始化在Qt应用程序中,首先要创建一个QApplication对象,QApplication类负责图形用户界面应用程序的控制流和主设置,在main.cpp中定义如下:int main(int argc,char*argv)QApplication a(argc,argv);2006 Embedded 1.1.1.1.初始化初始化初始化初始化QApplic
6、ation包含在main()函数的事件循环体中,对所有来自Window系统和其它源文件的事件进行处理和调度,还包括处理应用程序的初始化和结束,并且提供会话管理。在Qt应用程序中,不管有多少个窗口,QApplication对象只能有一个,而且必须在其他对象之前创建。QApplication类中封装了很多函数,其中包括:系统设置:setFont()用来设置字体事件处理:sendEvent()用来发送事件GUI风格:setStyles()设置图形用户界面的风格颜色使用:colorSpec()用来返回颜色文件文本处理:translate()用来处理文本信息创建组件:setmainWidget()用来设
7、置窗口的主组件 2006 Embedded 2.2.2.2.窗口的创建窗口的创建窗口的创建窗口的创建在Qt程序中,创建窗口比较简单,只要在main.cpp文件中为ApplicationWindow建立一个指针:ApplicationWindow*mw=new ApplicatonWindow();ApplicationWindow是在Application.h中定义的类,它是一个QmainWindow的继承类 3.3.3.3.组件的创建组件的创建组件的创建组件的创建组件的创建需要调用相应组件的类,并在头文件中包含此类的头文件或者创建自定义类,继承以后组件类的功能#include“qpushbu
8、tton.h”class hello:public Qwidget 2006 Embedded 3.3.3.3.组件的创建组件的创建组件的创建组件的创建hello类继承了Qwidget类的特征,并加入了自定义的特征功能,同样需要在头文件中包含此类的头文件在main.cpp的函数中需要创建hello类的实例,或创建QPushButton类的实例,才可以使用hello h(string);hello h(string);QPushButton hello(“Hello,world!”,0);QPushButton hello(“Hello,world!”,0);如果组件本身可以作为主窗口,则无需设
9、置主窗口。在上例中,下压按钮创建时其构造函数中的第二个参数为0,表示按钮所在窗口为主窗口,不需要设置主窗口。否则需要调用QWidget成员函数setMainWidget()来进行设置h.setMainWidget(&h);h.setMainWidget(&h);组件创建时一般是不可见的,这样的好处在于避免大量组件创建时造成的屏幕闪烁现象,要使组件可见需要调用QWidget类的成员函数show()来显示组件h.show();h.show();2006 Embedded 4.4.4.4.事件事件事件事件在X程序中,敲击键盘,鼠标指针在窗口中的移动或鼠标按键动作等,都是事件在Xt中提供了提供了一种叫
10、做回调的事件处理方式。它通过翻译表,将事件映射为相应的动作,当组件得到事件通知,就去表中找出相应的动作例程进行处理。这种机制需要应用程序注册有关组件的回调函数或普通的事件处理函数,以分发循环Xt的事件Qt事件的处理过程:QApplication的事件循环体从事件队列中拾取本地窗口系统事件或其他事件,译成QEvent(),并送给QObject:event(),最后送给QWidget:event()分别对事件处理其实在Qt程序中,事件处理的方式也是回调,但与以往所不同的是,事件的发出和接收采用了信号(signal)和插槽(slot)机制,无须调用翻译表。利用信号和插槽进行对象间的通信是Qt的最主要
11、特征之一。2006 Embedded 4.4.4.4.事件事件事件事件当对象状态发生改变的时候,发出signal通知所有的slot接收signal,尽管它并不知道哪些函数定义了slot,而slot也同样不知道要接收怎样的signalsignal和slot机制真正实现了封装的概念,slot除了接收signal之外和其它的成员函数没有什么不同,而且signal和slot之间也不是一一对应 2006 EmbeddedSignalSignal和和SlotSlot的声明(的声明(1 1)在Qt程序设计中,凡是包含signal和slot的类中都要加上Q_OBJECT的定义,下面的例子给出了如何在一个类中定
12、义signal和slot:class Student:public QObjectclass Student:public QObject Q_OBJECTQ_OBJECTpublic:public:Student()myMark=0;Student()myMark=0;int mark()const return myMark;int mark()const return myMark;public slots:public slots:void setMark(int newMark);void setMark(int newMark);signals:signals:void markC
13、hanged(int newMark);void markChanged(int newMark);private:private:int myMark;int myMark;2006 EmbeddedSignalSignal和和SlotSlot的声明(的声明(2 2)signal的发出一般在事件的处理函数中,利用emit发出signal,在下面的例子中在在事件处理结束后发出signalvoid Student:setMark(int newMark)void Student:setMark(int newMark)if(newMark!=myMark)if(newMark!=myMark)m
14、yMark=newMark;myMark=newMark;emit markChanged(myMark);emit markChanged(myMark);2006 EmbeddedSignalSignal和和SlotSlot的连接(的连接(1 1)在signal和slot声明以后,需要使用connect()函数将它们连接起来。connect()函数属于QObject类的成员函数,它能够连接signal和slot,也可以用来连接signal和signal函数原形如下:bool connect(const QObject*sender,const char*bool connect(const
15、 QObject*sender,const char*signal,const char*member)constsignal,const char*member)const其中第一个和第三个参数分别指出signal和slot是属于那个对象或组件 2006 EmbeddedSignalSignal和和SlotSlot的连接(的连接(2 2)在使用connect()函数进行来接的时候,还需要用到SIGNAL()和SLOT()这两个宏,使用方法如下:QLabel*label=new QLabel;QLabel*label=new QLabel;QScrollBar*scroll=new QScro
16、llBar;QScrollBar*scroll=new QScrollBar;QObject:connect(scroll,QObject:connect(scroll,SIGNALSIGNAL(valueChanged(int),(valueChanged(int),label,label,SLOTSLOT(setNum(int);(setNum(int);2006 EmbeddedSignalSignal和和SlotSlot的连接方式(的连接方式(1 1)2006 EmbeddedSignalSignal和和SlotSlot的连接方式(的连接方式(2 2)同一个信号连接多个插槽connec
17、t(slider,SIGNAL(connect(slider,SIGNAL(valueChanged(int)valueChanged(int),spinBox,),spinBox,SLOT(setValue(int);SLOT(setValue(int);connect(slider,SIGNAL(connect(slider,SIGNAL(valueChanged(int)valueChanged(int),this,),this,SLOT(updateStatusBarIndicator(int);SLOT(updateStatusBarIndicator(int);多个信号连接到同一个
18、插槽connect(lcd,SIGNAL(overflow(),this,SLOT(connect(lcd,SIGNAL(overflow(),this,SLOT(handleMathError()handleMathError(););connect(calculator,SIGNAL(divisionByZero(),this,connect(calculator,SIGNAL(divisionByZero(),this,SLOT(SLOT(handleMathError()handleMathError(););2006 EmbeddedSignalSignal和和SlotSlot的连接
19、方式(的连接方式(3 3)一个信号连接到另一个信号connect(lineEdit,SIGNAL(textChanged(const QString&),this,connect(lineEdit,SIGNAL(textChanged(const QString&),this,SIGNAL(updateRecord(const QString&);SIGNAL(updateRecord(const QString&);取消一个连接disconnect(lcd,SIGNAL(overflow(),this,SLOT(handleMathError()disconnect(lcd,SIGNAL(o
20、verflow(),this,SLOT(handleMathError(););取消一个连接不是很常用,因为Qt会在一个对象被删除后自动取消这个对象所包含的所有的连接 2006 Embedded退出事件程序退出事件程序退出事件程序,只需要在程序结束时返回一个exec(),例如:return a.exec();return a.exec();其中a为QApplication的实例,当调用exec()将进入主事件的循环中,直到exit()被调用或主窗口部件被销毁 2006 Embedded整个整个QtQt程序的执行过程程序的执行过程 2006 Embedded实验步骤(实验步骤(1 1)arm-l
21、inux-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从ftp:/embedded:embedded192.168.1.54下载到/root在root的主目录里面解压;minjunlocalhost$tar jxf arm-linux-gcc-3.4.1.tar.bz2-C/设置环境变量将arm-linux-gcc的路径加入PATH中,更改当前用户的.bashrc文件,在该文件中增加
22、一行脚本:export PATH=/usr/local/arm/3.4.1/bin:$PATH使环境变量立即生效minjunlocalhost$source.bashrc 2006 Embedded实验步骤(实验步骤(1 1)解压缩qt-embedded-env.tar.gz 该文件可以从ftp:/embedded:embedded192.168.1.54下载。针对redhat9的环境,将这次实验所需的tmake-1.13、qt-x11-2.3.2和qt-embedded-2.3.10预先编译后,打包成qt-embedded-env.tar.gz。实验时只要在/root目录下解压缩后设置相关环
23、境变量,就可以进行qt/embedded程序的开发。2006 Embedded实验步骤(实验步骤(2 2)安装)安装qt embeddedqt embedded开发环境开发环境在当前用户的主目录内,解压qt-embedded-env.tar.gzminjunlocalhost$tar zxf qt-embedded-env.tar.gzminjunlocalhost$tar zxf qt-embedded-env.tar.gz在解压后会得到两个目录在解压后会得到两个目录qt/qt/和和 qtopia_env/;qtopia_env/;其中其中qtopia_env/qtopia_env/下面的文
24、件是用来在开发程序时配置环境下面的文件是用来在开发程序时配置环境变量的变量的qvfb.sh 设置设置PCPC上的上的X11 qvfbX11 qvfb环境环境,包括需要的库和包括需要的库和tmaketmake环境变量等环境变量等target.sh 设置交叉编译时需要的环境变量设置交叉编译时需要的环境变量,包括包括tmaketmake的环境变量等的环境变量等其中其中qt/qt/目录下有三个子目录,分别是目录下有三个子目录,分别是qt-2.3.2 qt-2.3.2 qt-2.3.10 qt-2.3.10 编译编译X11 qvfbX11 qvfb环境下程序所需要的环境下程序所需要的qteqte环境环境
25、qt-embedded-2.3.10 qt-embedded-2.3.10 交叉编译交叉编译ARMARM开发板上程序所需要的开发板上程序所需要的qteqte环境环境 2006 Embedded实验步骤(实验步骤(3 3)编写运行)编写运行qvfbqvfb环境下的程序环境下的程序设置环境变量相关的环境变量设置在qtopia_env/目录下的qvfb.sh中minjunlocalhost qtopia_env$source qvfb.sh运行qvfb程序minjunlocalhost qt-2.3.10$qvfb&默认启动时,qvfb窗口大小为240320可以在启动时指定参数:qvfb-width
26、 640-height 480&2006 Embedded实验步骤(实验步骤(3 3)编写运行)编写运行qvfbqvfb环境下的程序环境下的程序接着,可以运行qt-2.3.10/examples/里面的example程序minjunlocalhost launcher$launcher-qws 2006 Embedded实验步骤(实验步骤(3 3)编写运行)编写运行qvfbqvfb环境下的程序环境下的程序下面通过编写一个“Hello Embedded”程序来了解Qt。首先新建一个目录(如hello):在hello/目录下建立如下文件:#include#include int main(int
27、argc,char*argv)QApplication app(argc,argv);QLabel*hello=new QLabel(hello Qt/Embedded!,0);app.setMainWidget(hello);hello-show();return app.exec();2006 Embedded分析分析hello.cpp程序第1 行和第2 行包含了两个头文件,这两个头文件中包含了QApplication 和 QLabel类的定义。第5 行创建了一个QApplication 对象,用于管理整个程序的资源,它需要2 个参数,因为Qt 本身需要一些命令行的参数。第6 行创建了一个
28、用来显示Hello Qt/Embedded!的部件。在Qt 中,部件是一个可视化用户接口,按钮、菜单、滚动条都是部件的实例。部件可以包含其它部件,例如,一个应用程序窗口通常是一个包含QMenuBar、QToolBar、QStatusBar 和其它部件的一个部件。在QLabel 函数中的参数0 表示,这是一个窗口而不是嵌入到其它窗口中的部件。第7 行设置hello 部件为程序的主部件,当用户关闭主部件后,应用程序将会被关闭。如果没有主部件的话,即使用户关闭了窗口程序也会在后台继续运行。第8 行使hello 部件可视,一般来说部件被创建后都是被隐藏的,因此可以在显示前根据需要来订制部件,这样的好处
29、是可以避免部件创建所造成的闪烁。第9 行把程序的控制权交还给Qt,这时候程序进入就绪模式,可是随时被用户行为激活,例如点击鼠标、敲击键盘等。2006 Embedded实验步骤(实验步骤(3 3)编写运行)编写运行qvfbqvfb环境下的程序环境下的程序程序的编译和运行在配置好环境变量后,要在qvfb中运行程序需要如下的步骤1.1.生成工程文件(生成工程文件(.pro.pro)rootlocalhost$progen-t app.t-o hello.prorootlocalhost$progen-t app.t-o hello.pro2.2.生成生成MakefileMakefile文件文件roo
30、tlocalhost$tmake-o Makefile hello.prorootlocalhost$tmake-o Makefile hello.pro3.3.编译编译rootlocalhost$makerootlocalhost$make4.4.运行运行(确保确保qvfb qvfb 在后台运行在后台运行)rootlocalhost$./hello-qwsrootlocalhost$./hello-qws 2006 Embedded实验步骤(实验步骤(4 4)用)用QT DesignerQT Designer设计图形界面设计图形界面使用Qt Designer可以方便地设计出图形界面,一般需要
31、如下的步骤创建和初始化子部件 设置子部件的布局 设置Tab键的次序 建立信号与插槽的连接 下面通过一个简单的例子来体验一下Qt Designer的使用涉及的控件:一个dial控件(上面的控件)一个Slider控件(下面的控件)实现的功能拖动slider时,dial中的指针会随着转动用鼠标拖动dial中的指针的时候,slider指示会变化 2006 Embedded实验步骤(实验步骤(4 4)用)用QT DesignerQT Designer设计图形界面设计图形界面启动Qt Designer(在$QT2DIR/bin里面,QT2DIR即qt-2.3.2/所在的目录)rootlocalhost t
32、est#$QT2DIR/bin/designer新建一个dialog 2006 Embedded实验步骤(实验步骤(4 4)用)用QT DesignerQT Designer设计图形界面设计图形界面将所需的控件加入到dialog中调整布局,使用工具栏上面的布局的控件进行调整,右图使用 2006 Embedded实验步骤(实验步骤(4 4)用)用QT DesignerQT Designer设计图形界面设计图形界面建立信号与插槽的连接 首先是slider发送signal、dial接收的情况点击signal/slot的图标在鼠标左键被按下的情况下连接slider和dial控件,出现如下对话框在sig
33、nal栏中选择vlaueChanged(int),在slot栏中选择setValue(int)然后点击connect按钮得到连接同理,可以得到dial发送信号,而slider接收的情况 2006 Embedded实验步骤(实验步骤(4 4)用)用QT DesignerQT Designer设计图形界面设计图形界面保存ui文件将生成的ui文件保存到项目所在目录中(请专门建立一个项目的目录,里面不要有无关的文件),比如存为form.ui根据ui文件编写包含main函数的cpp文件内容如下#include#include“form.h“/*头文件名称与ui文件名称相同*/int main(int a
34、rgc,char*argv)QApplication app(argc,argv);Form1 form;/*默认创建的类是Form1,可以在Designer的属性窗口中进行修改*/app.setMainWidget(&form);form.show();return app.exec();2006 Embedded实验步骤(实验步骤(5 5)编译和运行程序)编译和运行程序为qvfb编译程序首先设置环境变量(qtopia_env/目录下的qvfb.sh):rootlocalhost:test source/qtopia_env/qvfb.shsource/qtopia_env/qvfb.sh进
35、入项目的目录进入项目的目录rootlocalhost:test progen-t app.t -o form.prorootlocalhost:test tmake-o Makefile form.prorootlocalhost:test make得到编译完成的二进制文件运行如右图所示rootlocalhost:test./form-qws 2006 Embedded实验步骤(实验步骤(5 5)编译和运行程序)编译和运行程序为目标板编译程序首先设置环境变量(qtopia_env/目录下的target.sh):rootlocalhost:test source/qtopia_env/targe
36、t.shsource/qtopia_env/target.sh进入项目的目录进入项目的目录rootlocalhost:test progen-t app.t -o form.prorootlocalhost:test tmake-o Makefile form.prorootlocalhost:test make得到编译完成的二进制文件,将其上传到目标板上设置相应的环境变量(见下一页)运行程序mnt/yaffa ./form qwsqws结构如下页图所示结构如下页图所示 2006 Embedded实验步骤(实验步骤(5 5)设置)设置qt embeddedqt embedded运行环境运行环境
37、将qt-embedded-2.3.10/lib/qt-embedded-2.3.10/lib/目录下的目录下的libqte.so.2.3.10libqte.so.2.3.10传到开传到开发板的发板的/mnt/yaffs/Qtopia/lib/mnt/yaffs/Qtopia/lib目录下面,并建立如下的连接目录下面,并建立如下的连接/mnt/yaffs/Qtopia/lib ln-sf libqte.so.2.3.10 libqte.so.2.3/mnt/yaffs/Qtopia/lib ln-sf libqte.so.2.3.10 libqte.so.2.3/mnt/yaffs/Qtopia
38、/lib ln-sf libqte.so.2.3.10 libqte.so.2/mnt/yaffs/Qtopia/lib ln-sf libqte.so.2.3.10 libqte.so.2/mnt/yaffs/Qtopia/lib ln-sf libqte.so.2.3.10 libqte.so/mnt/yaffs/Qtopia/lib ln-sf libqte.so.2.3.10 libqte.so为了能够运行为了能够运行qt embeddedqt embedded的程序,请在目标板上设置如的程序,请在目标板上设置如下的环境变量下的环境变量export QTDIR=/usr/qpeexpo
39、rt QTDIR=/usr/qpeexport KDEDIR=/usr/qpeexport KDEDIR=/usr/qpeexport LD_LIBRARY_PATH=/usr/qpe/libexport LD_LIBRARY_PATH=/usr/qpe/libexport QWS_MOUSE_PROTO=“TPanel:/dev/input/event0 USB”export QWS_MOUSE_PROTO=“TPanel:/dev/input/event0 USB”2006 Embedded实验步骤(实验步骤(5 5)编译和运行程序)编译和运行程序在目标板上的操作需要USB鼠标的支持!2006 Embedded考试时间:7月10日上午8:3011:00 地点:主M405 2006 Embedded开始实验