Web开发

首页 » 常识 » 常识 » 物联网嵌入式工程师
TUhjnbcbe - 2025/5/12 18:49:00

物联网/嵌入式工程师-基于标准C库的文件操作

C语言文件操作详解C语言中没有输入输出语句,所有的输入输出功能都用ANSIC提供的一组标准库函数来实现。文件操作标准库函数有:
  
  文件的打开操作fopen打开一个文件
  
  文件的关闭操作fclose关闭一个文件
  
  文件的读写操作fgetc从文件中读取一个字符
  
  
  
  
   fputc写一个字符到文件中去
  
  
  
  
   fgets从文件中读取一个字符串
  
  
  
  
   fputs写一个字符串到文件中去
  
  
  
  
   fprintf往文件中写格式化数据
  
  
  
  
   fscanf格式化读取文件中数据
  
  
  
  
   fread以二进制形式读取文件中的数据
  
  
  
  
   fwrite以二进制形式写数据到文件中去
  
  
  
  
   getw以二进制形式读取一个整数
  
  
  
  
   putw以二进制形式存贮一个整数
   文件状态检查函数feof文件结束
  
  
  
  
   ferror文件读/写出错
  
  
  
  
   clearerr清除文件错误标志
  
  
  
  
   ftell了解文件指针的当前位置
  
  
  文件定位函数rewind反绕
  
  
  
  
   fseek随机定位#文件的打开 1.函数原型FILE*fopen(char*pname,char*mode) 2.功能说明
  按照mode规定的方式,打开由pname指定的文件。若找不到由pname指定的相应文件,就按以下方式之一处理:(1)此时如mode规定按写方式打开文件,就按由pname指定的名字建立一个新文件;(2)此时如mode规定按读方式打开文件,就会产生一个错误。打开文件的作用是:(1)分配给打开文件一个FILE类型的文件结构体变量,并将有关信息填入文件结构体变量;(2)开辟一个缓冲区;()调用操作系统提供的打开文件或建立新文件功能,打开或建立指定文件;FILE*:指出fopen是一个返回文件类型的指针函数; .参数说明pname:是一个字符指针,它将指向要打开或建立的文件的文件名字符串。mode:是一个指向文件处理方式字符串的字符指针。所有可能的文件处理方式见表8.1 4.返回值
   正常返回:被打开文件的文件指针。
   异常返回:NULL,表示打开操作不成功。例如://定义一个名叫fp文件指针FILE*fp;//判断按读方式打开一个名叫test的文件是否失败if((fp=fopen("test","r"))==NULL)//打开操作不成功{printf("Thefilecannotbeopened.\n"); exit(1);//结束程序的执行} 要说明的是:C语言将计算机的输入输出设备都看作是文件。例如,键盘文件、屏幕文件等。ANSIC标准规定,在执行程序时系统先自动打开键盘、屏幕、错误三个文件。这三个文件的文件指针分别是:标准输入stdin、标准输出stdout和标准出错stderr。*文件的关闭1.函数原型intfclose(FILE*fp);2.功能说明
  关闭由fp指出的文件。此时调用操作系统提供的文件关闭功能,关闭由fp-fd指出的文件;释放由fp指出的文件类型结构体变量;返回操作结果,即0或EOF。.参数说明
  fp:一个已打开文件的文件指针。4.返回值
  正常返回:0。
  异常返回:EOF,表示文件在关闭时发生错误。例如:intn=fclose(fp);*文件的读写操作A.从文件中读取一个字符
  1.函数原型intfgetc(FILE*fp);
  2.功能说明
  
  从fp所指文件中读取一个字符。
  .参数说明
  
  fp:这是个文件指针,它指出要从中读取字符的文件。
  4.返回值
  
  正常返回:返回读取字符的代码。
  
  非正常返回:返回EOF。例如,要从"写打开"文件中读取一个字符时,会发生错误而返回一个EOF。
  5.实例显示指定文件的内容。//程序名为:display.c//执行时可用:displayfilename1形式的命令行运行。显示文件filename1中的内容。例如,执行命令行displaydisplay.c将在屏幕上显示display的原代码。//Filedisplayprogram.#includestdio.hvoidmain(intargc,char*argv[])//命令行参数{intch;//定义文件类型指针FILE*fp;//判断命令行是否正确if(argc!=2){printf("Errorformat,Usage:displayfilename1\n");return;//键入了错误的命令行,结束程序的执行}//按读方式打开由argv[1]指出的文件if((fp=fopen(argv[1],"r"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);//打开操作不成功return;//结束程序的执行}//成功打开了argv[1]所指文件ch=fgetc(fp);//从fp所指文件的当前指针位置读取一个字符while(ch!=EOF)//判断刚读取的字符是否是文件结束符{putchar(ch);//若不是结束符,将它输出到屏幕上显示ch=fgetc(fp);//继续从fp所指文件中读取下一个字符}//完成将fp所指文件的内容输出到屏幕上显示fclose(fp);//关闭fp所指文件}B.写一个字符到文件中去1.函数原型intfputc(intch,FILE*fp)2.功能说明
  把ch中的字符写入由fp指出的文件中去。.参数说明
  ch:是一个整型变量,内存要写到文件中的字符(C语言中整型量和字符量可以通用)。
  fp:这是个文件指针,指出要在其中写入字符的文件。4.返回值
  正常返回:要写入字符的代码。
  非正常返回:返回EOF。例如,要往"读打开"文件中写一个字符时,会发生错误而返回一个EOF。5.实例将一个文件的内容复制到另一个文件中去。//程序名为:copyfile.c//执行时可用:copyfilefilename1filename2形式的命令行运行,将文件filename1中的内容复制到文件filename2中去。//filecopyprogram.#includestdio.hvoidmain(intargc,char*argv[])//命令行参数{intch;FILE*in,*out;//定义in和out两个文件类型指针if(argc!=)//判断命令行是否正确{printf("Errorinformat,Usage:copyfilefilename1filename2\n");return;//命令行错,结束程序的执行}//按读方式打开由argv[1]指出的文件if((in=fopen(argv[1],"r"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);return;//打开失败,结束程序的执行}//成功打开了argv[1]所指文件,再//按写方式打开由argv[2]指出的文件if((out=fopen(argv[2],"w"))==NULL){printf("Thefile%scannotbeopened.\n",argv[2]);return;//打开失败,结束程序的执行}//成功打开了argv[2]所指文件ch=fgetc(in);//从in所指文件的当前指针位置读取一个字符while(ch!=EOF)//判断刚读取的字符是否是文件结束符{fputc(ch,out);//若不是结束符,将它写入out所指文件ch=fgetc(in);//继续从in所指文件中读取下一个字符}//完成将in所指文件的内容写入(复制)到out所指文件中fclose(in);//关闭in所指文件fclose(out);//关闭out所指文件}按十进制和字符显示文件代码,若遇不可示字符就用井号"#"字符代替之。//程序名为:dumpf.c//执行时可用:dumpffilename1形式的命令行运行。//Filedumpprogram.#includestdio.hvoidmain(intargc,char*argv[]){charstr[9];intch,count,i;FILE*fp;if(argc!=2){printf("Errorformat,Usage:dumpffilename\n");return;}if((fp=fopen(argv[1],"r"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);return;}count=0;do{i=0;//按八进制输出第一列,作为一行八个字节的首地址printf("%06o:",count*8);do{//从打开的文件中读取一个字符ch=fgetc(fp);//按十进制方式输出这个字符的ASCII码printf("%4d",ch);//如果是不可示字符就用"#"字符代替if(ch

ch~)str=#;//如果是可示字符,就将它存入数组str以便形成字符串elsestr=ch;//保证每一行输出八个字符if(++i==8)break;}while(ch!=EOF);//遇到文件尾标志,结束读文件操作str=\0;//在数组str加字符串结束标志for(;i8;i++)printf("");//一行不足八个字符用空格填充printf("%s\n",str);//输出字符串count++;//准备输出下一行}while(ch!=EOF);//直到文件结束fclose(fp);//关闭fp所指文件}C.从文件中读取一个字符串1.函数原型
  char*fgets(char*str,intn,FILE*fp)2.功能说明
  从由fp指出的文件中读取n-1个字符,并把它们存放到由str指出的字符数组中去,最后加上一个字符串结束符\0。.参数说明
  str:接收字符串的内存地址,可以是数组名,也可以是指针。
  n:指出要读取字符的个数。
  fp:这是个文件指针,指出要从中读取字符的文件。4.返回值正常返回:返回字符串的内存首地址,即str的值。非正常返回:返回一个NULL值,此时应当用feof()或ferror()函数来判别是读取到了文件尾,还是发生了错误。例如,要从"写打开"文件中读取字符串,将发生错误而返回一个NULL值。D.写一个字符串到文件中去1.函数原型intfputs(char*str,FILE*fp)2.功能说明
  把由str指出的字符串写入到fp所指的文件中去。.参数说明
  str:指出要写到文件中去的字符串。
  fp:这是个文件指针,指出字符串要写入其中的文件。4.返回值
  正常返回:写入文件的字符个数,即字符串的长度。
  非正常返回:返回一个NULL值,此时应当用feof()或ferror()函数来判别是读取到了文件尾,还是发生了错误。例如,要往一个"读打开"文件中写字符串时,会发生错误而返回一个NULL值。5.实例以下程序将一个文件的内容附加到另一个文件中去。//程序名:linkfile.c//执行时可用:linkfilefilename1filename2形式的命令行运行,将文件filename2的内容附加在文件filename1之后。//filelinkedprogram.#includestdio.h#defineSIZEvoidmain(intargc,char*argv[]){charbuffer[SIZE];FILE*fp1,*fp2;if(argc!=){printf("Usage:linkfilefilename1filename2\n");return;}//按追加方式打开argv[1]所指文件if((fp1=fopen(argv[1],"a"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);return;}if((fp2=fopen(argv[2],"r"))==NULL){printf("Thefile%scannotbeopened.\n",argv[2]);return;}//读入一行立即写出,直到文件结束while(fgets(buffer,SIZE,fp1)!=NULL)printf("%s\n",buffer);while(fgets(buffer,SIZE,fp2)!=NULL)fputs(buffer,fp1);fclose(fp1);fclose(fp2);if((fp1=fopen(argv[1],"r"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);return;}while(fgets(buffer,SIZE,fp1)!=NULL)printf("%s\n",buffer);fclose(fp1);}E.往文件中写格式化数据1.函数原型intfprintf(FILE*fp,char*format,arg_list)2.功能说明
  将变量表列(arg_list)中的数据,按照format指出的格式,写入由fp指定的文件。fprintf()函数与printf()函数的功能相同,只是printf()函数是将数据写入屏幕文件(stdout)。.参数说明
  fp:这是个文件指针,指出要将数据写入的文件。
  format:这是个指向字符串的字符指针,字符串中含有要写出数据的格式,所以该字符串成为格式串。格式串描述的规则与printf()函数中的格式串相同。arg_list:是要写入文件的变量表列,各变量之间用逗号分隔。4.返回值
  无。5.实例下列程序的执行文件为display.exe,执行时键入命令行:
   display[-i][-s]filename下面的表格列出了命令行参数的含义及其功能://存储文件名:save.txt//程序代码如下://filedisplayprogram.#includestdio.hvoidmain(){charname[10];intnAge,nClass;longnumber;FILE*fp;if((fp=fopen("student.txt","w"))==NULL){printf("Thefile%scannotbeopened.\n","student.txt");return;}fscanf(stdin,"%s%d%d%ld",name,nClass,nAge,number);fprintf(fp,"%s%5d%4d%8ld",name,nClass,nAge,number);fclose(fp);if((fp=fopen("student.txt","r"))==NULL){printf("Thefile%scannotbeopened.\n","student.txt");return;}fscanf(fp,"%s%d%d%ld",name,nClass,nAge,number);printf("namenClassnAgenumber\n");fprintf(stdout,"%-10s%-8d%-6d%-8ld\n",name,nClass,nAge,number);fclose(fp);}G.以二进制形式读取文件中的数据1.函数原型intfread(void*buffer,unsignedsife,unsignedcount,FILE*fp)2.功能说明
  从由fp指定的文件中,按二进制形式将sife*count个数据读到由buffer指出的数据区中。.参数说明buffer:这是一个void型指针,指出要将读入数据存放在其中的存储区首地址。sife:指出一个数据块的字节数,即一个数据块的大小尺寸。count:指出一次读入多少个数据块(sife)。fp:这是个文件指针,指出要从其中读出数据的文件。4.返回值
  正常返回:实际读取数据块的个数,即count。
  异常返回:如果文件中剩下的数据块个数少于参数中count指出的个数,或者发生了错误,返回0值。此时可以用feof()和ferror()来判定到底出现了什么情况。H.以二进制形式写数据到文件中去1.函数原型intfwrite(void*buffer,unsignedsife,unsignedcount,FILE*fp)2.功能说明
  按二进制形式,将由buffer指定的数据缓冲区内的sife*count个数据写入由fp指定的文件中去。.参数说明buffer:这是一个void型指针,指出要将其中数据输出到文件的缓冲区首地址。sife:指出一个数据块的字节数,即一个数据块的大小尺寸。count:一次输出多少个数据块(sife)。fp:这是个文件指针,指出要从其中读出数据的文件。4.返回值
  正常返回:实际输出数据块的个数,即count。
  异常返回:返回0值,表示输出结束或发生了错误。5.实例#includestdio.h#defineSIZE4structworker{intnumber;charname[20];intage;};voidmain(){structworkerwk;intn;FILE*in,*out;if((in=fopen("file1.txt","rb"))==NULL){printf("Thefile%scannotbeopened.\n","file1.txt");return;}if((out=fopen("file2.txt","wb"))==NULL){printf("Thefile%scannotbeopened.\n","file2.txt");return;}while(fread(wk,sizeof(structworker),1,in)==1)fwrite(wk,sizeof(structworker),1,out);fclose(in);fclose(out);}I.以二进制形式读取一个整数1.函数原型intgetw(FILE*fp)2.功能说明
  从由fp指定的文件中,以二进制形式读取一个整数。.参数说明
  fp:是文件指针。4.返回值
  正常返回:所读取整数的值。
  异常返回:返回EOF,即-1。由于读取的整数值有可能是-1,所以必须用feof()或ferror()来判断是到了文件结束,还是出现了一个出错。5.实例#includestdio.hvoidmain(intargc,char*argv[]){inti,sum=0;FILE*fp;if(argc!=2){printf("Commanderror,Usage:readfilefilename\n");exit(1);}if(!(fp=fopen(argv[1],"rb"))){printf("Thefile%scannotbeopened.\n",argv[1]);exit(1);}for(i=1;i=10;i++)sum+=getw(fp);printf("Thesumis%d\n",sum);fclose(fp);}J.以二进制形式存贮一个整数1.函数原型intputw(intn,FILE*fp)2.功能说明 以二进制形式把由变量n指出的整数值存放到由fp指定的文件中。.参数说明 n:要存入文件的整数。 fp:是文件指针。4.返回值 正常返回:所输出的整数值。 异常返回:返回EOF,即-1。由于输出的整数值有可能是-1,所以必须用feof()或ferror()来判断是到了文件结束,还是出现了一个出错。5.实例#includestdio.hvoidmain(intargc,char*argv[]){inti;FILE*fp;if(argc!=2){printf("Commanderror,Usage:writefilefilename\n");return;}if(!(fp=fopen(argv[1],"wb"))){printf("Thefile%scannotbeopened.\n",argv[1]);return;}for(i=1;i=10;i++)printf("%d\n",putw(i,fp));fclose(fp);}*文件状态检查A.文件结束(1)函数原型intfeof(FILE*fp)(2)功能说明
   该函数用来判断文件是否结束。()参数说明
   fp:文件指针。(4)返回值
   0:假值,表示文件未结束。
   1:真值,表示文件结束。(5)实例#includestdio.hvoidmain(intargc,char*argv[]){FILE*in,*out;charch;if(argc!=){printf("Usage:copyfilefilename1filename2\n");return;}if((in=fopen(argv[1],"rb"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);return;}if((out=fopen(argv[2],"wb"))==NULL){printf("Thefile%scannotbeopened.\n",argv[2]);return;}while(!feof(in)){ch=fgetc(in);if(ferror(in)){printf("readerror!\n");clearerr(in);}else{fputc(ch,out);if(ferror(out)){printf("writeerror!\n");clearerr(out);}}}fclose(in);fclose(out);}B.文件读/写出错(1)函数原型intferror(FILE*fp)(2)功能说明
   检查由fp指定的文件在读写时是否出错。()参数说明
   fp:文件指针。(4)返回值
   0:假值,表示无错误。
   1:真值,表示出错。C.清除文件错误标志(1)函数原型voidclearerr(FILE*fp)(2)功能说明
   清除由fp指定文件的错误标志。()参数说明
   fp:文件指针。(4)返回值
   无。(5)实例#includestdio.hvoidmain(intargc,char*argv[]){FILE*in,*out;charch;if(argc!=){printf("Usage:copyfilefilename1filename2\n");return;}if((in=fopen(argv[1],"rb"))==NULL){printf("Thefile%scannotbeopened.\n",argv[1]);return;}if((out=fopen(argv[2],"wb"))==NULL){printf("Thefile%scannotbeopened.\n",argv[2]);return;}while(!feof(in)){ch=fgetc(in);if(ferror(in)){printf("readerror!\n");clearerr(in);}else{fputc(ch,out);if(ferror(out)){printf("writeerror!\n");clearerr(out);}}}fclose(in);fclose(out);}D.了解文件指针的当前位置(1)函数原型longftell(FILE*fp)(2)功能说明
   取得由fp指定文件的当前读/写位置,该位置值用相对于文件开头的位移量来表示。()参数说明
   fp:文件指针。(4)返回值
   正常返回:位移量(这是个长整数)。
   异常返回:-1,表示出错。(5)实例*文件定位A.反绕(1)函数原型voidrewind(FILE*fp)(2)功能说明
   使由文件指针fp指定的文件的位置指针重新指向文件的开头位置。()参数说明
   fp:文件指针。(4)返回值
   无。(5)实例#includestdio.hvoidmain(){FILE*in,*out;in=fopen("filename1","r");out=fopen("filename2","w");while(!feof(in))fputc(fgetc(in),out);rewind(out);while(!feof(in))putchar(fgetc(in));fclose(in);fclose(out);}B.随机定位(1)函数原型intfseek(FILE*fp,longoffset,intbase)(2)功能说明
   使文件指针fp移到基于base的相对位置offset处。()参数说明
   fp:文件指针。
   offset:相对base的字节位移量。这是个长整数,用以支持大于64KB的文件。
   base:文件位置指针移动的基准位置,是计算文件位置指针位移的基点。ANSIC定义了base的可能取值,以及这些取值的符号常量。(4)返回值
  正常返回:当前指针位置。
  异常返回:-1,表示定位操作出错。(5)实例#includestdio.h#includestring.hstructstd_type{intnum;charname[20];intage;charclass;}stud;intcstufile(){inti;FILE*fp;if((fp=fopen("stufile","wb"))==NULL){printf("Thefilecantbeopenedforwrite.\n");return0;}for(i=1;i=;i++){stud.num=i;strcpy(stud.name,"aaaa");stud.age=17;stud.class=8;fwrite(stud,sizeof(structstd_type),1,fp);}fclose(fp);return1;}voidmain(){intn;FILE*fp;if(cstufile()==0)return;if((fp=fopen("stufile","rb"))==NULL){printf("Thefilecannotbeopened.\n");return;}for(n=0;n;n+=2){fseek(fp,n*sizeof(structstd_type),SEEK_SET);fread(stud,sizeof(structstd_type),1,fp);printf("%10d%20s%10d%4c\n",stud.num,stud.name,stud.age,stud.class);}fclose(fp);}*关于exit()函数1.函数原型voidexit(intstatus)2.功能说明
  exit()函数使程序立即终止执行,同时将缓冲区中剩余的数据输出并关闭所有已经打开的文件。.参数说明
  status:为0值表示程序正常终止,为非0值表示一个定义错误。4.返回值
  无。*关于feof()函数1.函数原型intfeof(FILE*fp)2.功能说明  在文本文件(ASCII文件)中可以用值为-1的符号常量EOF来作为文件的结束符。但是在二进制文件中-1往往可能是一个有意义的数据,因此不能用它来作为文件的结束标志。为了能有效判别文件是否结束,ANSIC提供了标准函数feof(),用来识别文件是否结束。.参数说明
  fp:文件指针。4.返回值
  返回为非0值:已到文件尾。
  返回为0值:表示还未到文件尾。

物联网/嵌入式工程师-嵌入式产品人机交互QT框架

Qt是什么?


  1、Qt是一个年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。
  2、Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(MetaObjectCompiler,moc))以及一些宏,易于扩展,允许组件编程。
  、年,奇趣科技被诺基亚公司收购,QT也因此成为诺基亚旗下的编程语言工具。年,Qt被Digia收购。
  4、年4月,跨平台集成开发环境QtCreator.1.0正式发布,实现了对于iOS的完全支持,新增WinRT、Beautifier等插件,废弃了无Python接口的GDB调试支持,集成了基于Clang的C/C++代码模块,并对Android支持做出了调整,至此实现了全面支持iOS、Android、WP。

Qt/Embedded和Qtopia介绍及其开发环境的建立目前嵌入式Linux的主流GUI系统主要有MiniGUI、Microwindows、OpenGUI、Qt/Embedded,这些GUI在接口定义、体系结构、功能特性存在很大差别,采取的技术路线也有所不同[1]。MiniGUI是建立在比较成熟的图形引擎之上,开发的重点在于窗口系统,其小巧精致并且尽量与Win2兼容。MicroWindows目前开发的重点在底层的图形引擎,窗口系统和图形接口方面功能比较欠缺,与Win2和XWindows窗口系统保持兼容,提供了相对完善的图形功能。OpenGUI基于一个用汇编实现的x86图形内核,提供了一个高层的C/C++图形/窗口接口,它的资源消耗小,可移植性差,不支持多进程。Qt/Embedded是一个多平台的C++图形用户界面应用程序框架,其对象容易扩展,可移植性好,支持多个GUI平台的交互开发[2,]。现在,Qt/Embedded被广泛地应用于各种嵌入式产品和设备中,从消费电器(如智能手机、机顶盒)到工业控制设备(如医学成像设备、移动信息系统等)。因此本文选择Qt/Embedded为本系统的GUI。(1)Qt/Embedded和Qtopia体系结构Qt/Embedded是Trolltech公司开发的面向嵌入式系统的Qt版本,与X11版本的Qt在最大程度上接口兼容,采用帧缓存(framebuffer)作为底层图形接口。Qt/Embedded类库完全采用C++封装,并且有着丰富的控件资源以及较好的可移植性,大范围的Qt/EmbeddedAPI可用于多种开发项目。Qt/Embedded的实现结构如图(2)所示:图(2)Qt/Embedded实现结构Qt/Embedded的底层图形引擎基于framebuffer。framebuffer是一种驱动程序接口,它将显示设备抽象为帧缓冲区[4]。该驱动程序的设备文件一般是/dev/fb0、/dev/fb1等。对用户而言,它和/dev下的其他设备没有什么区别,用户可以把framebuffer看成一块内存,既可以从这块内存中读取数据,也可以向其中写入数据,而写操作立即反应在屏幕上。为运行Qt/Embedded,嵌入式Linux内核要支持framebuffer。Qt/Embedded是Qt的面向嵌入式应用的简化版本,它包括一组完备的GUI类、操作系统封装、数据结构类、功能类和组合类。大部分Qt的应用程序可以经过简单的编译与重设窗口大小移植到Qt/Embedded。Qtopia是基于QT/Embedded开发的一个嵌入式的窗口系统和应用程序集,如地址本、图像浏览、Media播放器等,还包括娱乐和配置工具,广泛用于PDA等掌上设备。Qtopia平台由Qtopia库(Qt/E,libqpe,libqtopia1,qtopiapim)和Qtopiaserver/laucher组成。Qtopiaserver/laucher是控制窗口系统、进程间通信、发起所有应用和其他核心任务的主要服务程序。(2)Qt/Embedded和Qtopia的交叉编译与运行整个GUI系统的构建需要对Qt/Embedded、Qtopia依次分别编链,然后有机地整合在一起。Qt/Embedded为Qtopia提供了底层支持,GUI系统的图形库窗口组建都由Qt/Embedded实现。在构建GUI时用于Qt开发的典型工具如下:tmake:跨平台的Makefile生成器。moc:用于QtC++扩展的metra-object编译器。uic:从XML文件生成代码的用户界面编译器。designer:用于设计窗口组建的应用程序。Qtopia的开发工具包SDK(SoftwareDevelopmentKit)是Qtopia开发环境的核心部分,编译后得到创建应用程序所需的软件包如下:qvfb(virtualframebuffer):X窗口用来运行和测试Qtopia应用程序的系统程序。qpe(Qtopiaexecutable):用来处理所有的用户程序界面[2,5]。由于我们使用的是ARMCPU,因此需要对Qt/Embedded和Qtopia开发工具包进行交叉编译。本文使用arm-linux-gcc-..2来建立交叉编译环境。为了对Qt/Embedded和Qtopia进行交叉编译,需要使用如下的源码树:tmake-1.1.tar.gz:用来得到tmake工具。qt-embedded-2..7.tar.gz:Qt的嵌入式版本。qt-x11-2..2.tar.gz:Qt的X11版本。qtopia-free-1.7.0.tar.gz:官方网站提供的Qtopia免费版。e2fsprogs-1.8.tar.gz:为了得到qtopia所需的uuid.h和libuuid.so。假设将上述源码树放在同一目录下,例如:/root/qtopia,并依次解压,然后进行编译,步骤如下:①设定tmake的环境变量如下:exportTMAKEPATH=/root/qtopia/tmake-1.1/lib/qws/linux-arm-g++此处指定了tmake在生成Makefile时使用arm交叉编译。②编译qt-x11,其目的是生成moc、uic、qvfb、designer,并将它们放在qt-embedded\bin目录下。③配置qt-embedded编译选项,命令为:./configure-platformlinux-arm-g++-qconfigqpe-qvfb-depths4,8,16,2.此处-platformlinux-arm-g++表示在arm平台上进行交叉编译;-qconfiglocal表示使用src/tools/qconfig-local.h;-depths4,8,16,2表示需要qt支持的显示颜色深度。④使用make命令编译qt-embedded,用来生成Qt库(libqte.so)。⑤配置并交叉编译Qtopia,生成应用程序以及桌面环境。假设编译完成后将qt和qtopia相关的库及所需文件分别存放于目标板文件系统的/opt/qt和/opt/qtopia下,运行Qtopia的方法是:①设置QTDIR、QPEDIR和键盘鼠标等环境变量exportQTDIR=/opt/qtexportQPEDIR=/opt/qtopiaexportQWS_KEYBOARD=USB:/dev/input/event1exportQWS_MOUSE_PROTO=USB:/dev/input/mouse0②开启qpe,也就是在Linux图形模式下执行/opt/qtopia/bin/qpe这样就可以在显示终端上看到qtopia桌面环境了。4Qt/Embedded和Qtopia下应用程序的实现(1)Qt/Embedded应用程序的实现Qt是一个创建GUI程序的C++类库,编写Qt应用程序的主要工作是基于已有的Qt类编写用户类。Qt应用程序的设计使用基于工程的方法,并通过.pro文件进行工程管理。实现应用程序的第一步是编写.pro文件,然后使用tmake根据该文件生成Makefile,最后进行源代码的编写。tmake的语法如下:tmake*.pro–oMakefile.pro的具体内容可以参考/qt/examples/下其他应用程序的.pro文件。在本项目的研究中,需要涉及基本的窗口构建、应用程序的调用、图像背景的显示以及中文显示,下面对此进行详细阐述。构建主窗口Qt拥有众多的窗口部件,如按钮、菜单、滚动条和应用程序窗口等,它们组合起来可以创建各种用户界面。QWidget是所有用户界面对象的基类,窗口部件是QWidget或其子类的实例。创建主窗口先要在main.cpp函数中创建QApplication类型的对象。QApplication类管理图形用户界面应用程序的控制流和主要设置,它包含主事件循环,在其中来自窗口系统和其它资源的所有事件被处理和调度,它也处理应用程序的初始化和结束,并提供对话管理。对于任何一个使用Qt图形用户界面应用程序,都正好存在一个QApplication对象。然后定义主窗口变量,并通过QApplication类型的函数调用主窗口变量来启动主窗口。创建主窗口部件最常用的方法是基于QWidget或QDialog类创建一个用户类。QDialog类是对话框窗口的基类,主要用于短期任务以及和用户进行简要通讯的顶级窗口。在本程序中使用QWidget类创建用户类,并使用户类通过公有继承派生于Qwidget类。在构建窗口时需要注意用户界面的风格和布局。Qt提供了Windows、WindowsXP、Motif、MotifPlus、CDE、Platinum、SGI和Mac的内置风格。自定义风格可以通过继承QStyle、QCommonStyle或其他QCommenStyle类来完成。应用程序的风格可以如下设置:QApplication::setStyle(newMyCustomStyle)在布局上Qt提供了布局管理器来组织父部件区域中的子部件,Qt内建的布局管理器有QHBoxLayout,QVBoxLayout和QGridLayout,而且布局也可以嵌套在任意层。例如使用QHBoxLayout(按行放置部件)的部件管理器为例在窗口水平放置两个按钮B1和B2的代码如下:QHBoxLayout*hbox=newQHBoxLayout(this);Hbox-addWidget(B1);Hbox-addWidget(B2);创建按钮实现对应用程序的调用Qt部件与用户的交互方式不同于其他的GUI工具包,其他的GUI工具包使用回调函数创建用户交互,但是Qt提供了信号/槽(signal/slots)[5]通信机制描述对象间的无缝通讯。槽(slot)是标准的成员函数,它能够连接到信号,每当槽所连接的信号被发射时,槽(函数)就被执行。信号(signal)是一种特殊类型的函数,都是返回void型,它们被定义为当某个事件发生时就被发射,之后执行所有被连接的槽。当定义信号时必须使用QT的宏SIGNAL(),定义槽时必须使用宏SLOT()。通过调用QObject对象的connect函数可以将某个对象的信号与另一个对象的槽相关联,这样当发射对象发射信号时,接收对象的槽将被调用。该函数定义如下:boolQObject::connect(constQObject*sender,constchar*signal,constQObject*receiver,constchar*member)与这个函数对应的disconnect函数,可以将信号和槽断开连接。本文使用了QT库提供的按钮clicked()信号,自定义了槽函数run()来实现对应用程序的调用,并且定义了槽函数mycall()调用已经使用了特定参数的run()函数。例如当一个按钮B1被点击时,它就发送“clicked”信号,通过connect()函数将信号与槽“mycall”连接起来,调用/opt/qt/examples/clock/下的应用程序“clock”的代码如下:voidMyMainWindow::mycall(){MyMainWindow::run(“(cd/opt/qt/examples/clock;exec./clock;)”);}connect(B1,SIGNAL(clicked()),this,SLOT(mycall()));图像背景的显示为了在Qt中装载和显示所支持的图像格式,需要创建一个QPixmap对象。QPixmap本质上是一个“屏幕外的部件(off-screen)”,图像可以先复制到一个QPixmap对象上,然后传送到QWidget。QWidget部件使用如下的成员函数来为窗口添加图像背景:PublicMembersconstQPixmap*backgroundPixmap()constvirtualvoidsetBackgroundPixmap(constQPixmap)例如有一幅名为flower.png的图片,将其设为背景的代码如下:QPixmappicture(“flower.png”)SetbackgroundPixmap(picture)中文显示Qt的中文显示是Qt国际化的一部分,“国际化”简称为i18n,用来提供一个架构,让同样的代码可以适用于各种语种习惯和编码系统,程序设计人员只要利用这个架构的机制、准则编写应用程序,就可以在不新编译代码的情况下,支持各种语言。Qt支持Unicode—国际标准字符集,程序员可以在程序里自由的混用英语、汉语和其他Unicode所支持的语言。为Qt增加一种编码只需要增加该编码和Unicode的转化编码就可以了,Qt支持中文的GBK/Big5编码。Qt支持的字体常用的是ttf和qpf。qpf是Qt/Embedded专用的一种适合嵌入式应用的字体,它属于位图字体,不可以缩放,而ttf字体可以缩放。默认情况下Qt/Embedded在lib/fonts目录下提供了一种可以显示中文的字体库UniFont,但是该字体库中没有ttf的字体。为了使用ttf字体显示中文,本文采取如下的方法:拷贝一种支持unicode编码的ttf字体到lib/fonts目录下,例如,windows系统下的宋体simsun.ttf;同时还需要在此目录的fontdir脚本中添加下面一行:simsunsimsun.ttfFTnsufontdir脚本用来向系统注册所支持的字体,它的每一行定义了一种字体的设置,其格式如下:字体名称字体文件名字体渲染类型是否斜体尺寸字体标志[尺寸列表]在程序设计中,首先指定编码方式以支持中文:QTextCodec*code=QTextCodec::codecForName("GBK")接着为部件(例如Mywidget)执行Unicode的转化编码:QStringuniStr=code-toUnicode("要显示的中文字符")Mywidget-setFont(QFont("simsun",20,QFont::Bold))Mywidget-setText(uniStr)(2)向Qtopia移植应用程序Qtopia是一个基于QT/Embedded开发的一个嵌入式的桌面环境和应用程序集,可以方便地在Qtopia桌面环境中添加用户应用程序或者对桌面进行配置。为了添加用户应用程序,需要在Qtopia/apps/Application目录下建立一个.desktop的桌面文件,该文件指明了桌面文件的图标以及应用程序的入口点。应该注意的是为了让新的应用程序在Qtopia桌面环境中运行,应用程序必须使用QT提供的图形库进行编译。下面以移植嵌入式的web浏览器konqueror为例,说明添加新的应用程序的过程。下载konqueror源代码,对其进行交叉编译。为了支持中文显示和flash,还需要进行必要的源代码修改,并且加入相应的插件。将konqueror.png图标文件拷贝到在/opt/Qtopia/pic/下。将konqueror可执行文件放于/opt/konqueror/下,然后在Qtopia/apps/Application目录下建立konqueror.desktop文件,具体内容可参考qtopia自带的.desktop文件。需要注意的是konqueror.desktop的Exec项应指明可执行文件的具体位置。例如:Exec=/opt/konqueror/bin/konqueror导出konqueror的运行环境变量,就可以直接在桌面上点击其图标浏览网页了。-----------------------------------基于Qt/Embedded和Qtopia的GUI设计

1
查看完整版本: 物联网嵌入式工程师