免费预览已结束,剩余21页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Xx大学本科生毕业论文(设计)题目 Linux下图形界面mp3播放器的实现 姓名 xxx 学号 xxx 院系 计算机科学学院 专业 网络工程 指导教师 xxx 职称 讲师 200 年 月 日xxx教务处制目 录摘要关键词AbstractKey words引言1 主要相关技术介绍11 Linux的设计和用户界面12 Linux下的编程13 Makefile文件的编写14 关于GTK+15 GStreamer简介16 回调函数17 本程序的开发环境和使用到的一些工具2 编译环境的搭建和检测21 基本编译环境的搭建22 安装GTK/GNOME编译环境23 安装GStreamer编译环境3 程序的设计目标和分析31 程序设计目标32 需求分析4 程序的详细设计及编码41 程序文件的组织42 main.c文件43 图形界面的结构44 PLAY按钮45 菜单46 mp3文件的选取与文件名的显示47 GStreamer和文件的播放48 使用滑块来控制的播放进度49 实现的一点补充5 编译以及以后的工作51 Makefile文件的编写52 编译,安装,运行,卸载53 制作源代码安装包结束语致谢参考文献:Linux下图形界面mp3播放器的实现网络工程专业学生 xxx指导教师 xxx摘要:Linux作为自由和开源软件领域中最出色的例子,人们更多地了解其在服务器方面的应用。不过,由于Linux具有可移植度高、自由、免费等特性,最近几年,它在移动设备和个人电脑领域的应用也越来越广泛。鉴于以上应用领域对用户界面友好性方面的要求,几乎所有的此类应用都是采用图形用户界面。基于GTK的GNOME,是Linux领域中最主要的桌面环境。而GTK本身,则是创造图形用户界面的最流行的跨平台GUI工具箱之一。这里将通过一个使用GTK和GStreamer技术的简单mp3播放器的实现,详细描述Linux环境下的图形界面编程技术。关键词:Linux mp3播放器 GTK GStreamer C语言The Implementation of GUI Mp3 Player in LinuxStudent majoring in Network Engineering xxx Tutor xxxAbstract:As one of the most distinguished examples of free and open source software collaboration, Linux is predominantly known for its application in servers. However, Linux editions installed on both mobile devices and personal computers have become increasingly commonplace in recent years, owing largely to its highly portability and high degree of freedom. In view of the importance of user friendly operation, almost all of these editions are based on Graphical User Interface(GUI). Based on GTK, one of the most popular cross-platform widget toolkits for creating graphical user interfaces, Gnome is a dominant desktop environmentthe GUI which runs on top of a computer operating system. This paper mainly focused on the implementation of a simple GUI interfaced mp3 player using GTK and GStreamer technology under Gnome environment, will illustrate detailed steps on Linux GUI programming.Key words: Linux;mp3 Player;GTK;GStreamer;C引言随着半导体技术的高速发展,个人电脑和智能型掌上设备价格迅速下降,因而普及到学习、工作、生产等各个方面。然而,与硬件价格的迅速下降相比,软件价格不仅没有下降,反而有上升的趋势。一个典型的例子是,14年前,Windows 95面世时,个人电脑硬件的价格在一万元以上,Windows 95操作系统本身,只有一千多元;将于2009下半年发布的Windows 7的价格预计却仍维持在一千元以上(终极版为两千元以上),而个人电脑硬件的价格却下降到两千元左右。由此可见,软件成本已经成为信息化社会发展中不可忽视的一项支出。降低软件成本,最有效的办法就是使用和推广自由和开源软件,使用可移植性高的平台,做到一次开发,多处使用。Java就是一个成功的例子。Java初期的卖点是可移植性高,目前在保持这个优势的同时,Java克服了速度方面的缺陷,取得了极大的成功。而现在,Sun公司又推出了开源版的Java虚拟机,准备将Java的核心技术开源化。但Java不是万能的,Java的适用范围有限。在个人电脑领域和嵌入式系统的操作系统领域,我们有Linux。Linux是自由软件基金会的杰作,当然也就是完全开源的,完全免费的,另外,它还是容易移植的。Netcraft报告说,截止2006年9月,全球10大最可靠的因特网虚拟主机供应商中,有8家在他们的Web服务器上使用Linux。在超级计算机领域,Linux成绩更是耀眼:截止2008年12月,最快的500台超级计算机中,有439台使用各种Linux发行版本。不过,在个人电脑和智能型掌上设备领域,Linux的成果就没有那么显著了。我们看到, 使用Windows或者Mactonish的PC,使用Symbian操作系统的诺基亚智能手机,使用移动型Mactonish的苹果iPhone,使用微软嵌入式Windows的掌上电子设备,占据了绝大部分的市场。但是,凭借Linux的自由和免费,以及开发产品可移植性高的优势,Linux在硬件价格逐渐下降的过程中会逐渐显现出优势。正如大家看到的,市场已经对此做出反应。就本平台下的程序开发而言,与Windows相比,有国内开发人员少、中文相关学习材料不够的丰富、存在大量高质量的开源程序和软件,便于模仿学习、整个操作系统都是自由软件、所有源代码都可得到等特点。由此可见,由于操作系统源代码的开源和大量开源程序的存在,开发人员自身开发水平提高的余地比在Windows平台下更大,并且更容易参与到国际开源项目中,提升自己的英文水平。而GTK和GStreamer分别作为图形界面编程和媒体框架的两大技术,在Linux系统中有重要地位。现在,也有很多把两者结合起来的很好的产品,比如著名的Totem Movie Player和Rhythmbox Music Player等,但网上并没有推出一个简易并融合了这两大技术的产品。基于以上各方面的考虑,我将实现一个“Linux平台下的图形界面mp3播放器”作为毕业论文的课题。开发的过程将涉及到Linux软件开发的各个方面,有助于提升个人整合项目的水平,并为Linux社区的发展做出贡献。本文将结合GTK和GStreamer两大技术,同时使用Linux中几个代表性的软件,如:Gcc编译器,make等,详细阐述如何制作一个简单的mp3播放器。1 主要相关技术介绍11 Linux的设计和用户界面基于Linux内核的系统是一种模块化的类Unix系统。它继承了Unix在上世纪70、80年代发展起来的基本设计原则。这种系统使用单内核(与此相对应的是使用微内核的Windows)来处理进程控制、网络连接、外设和文件访问等应用。设备驱动和内核直接集成在一起。与内核交互的单独项目提供了系统的高级别功能。GNU用户区(userland)是大多数基于Linux系统的重要组成部分,它提供了最多的C库的常用实现,比如shell和一些其它的Unix工具。这些工具可以处理一些基本任务。基于Linux的系统可以用命令行(CLI)、图形用户界面(GUI通常也是系统的默认设置)等方式进行控制。在嵌入式设备上,也可以用设备本身的控制器进行控制。在桌面系统上,虽然存在很多图形用户界面,但GNOME、KDE和Xfce是其中最流行的。大多数流行的用户界面运行于X Window系统之上,它提供了网络透明性,可以让一台机器上的图形界面来控制另一台机器上运行的程序。当然,它也可以控制本机上的程序,这就是Linux 图形用户界面的实现策略。也就是说,天生就考虑到了远程控制。用远程控制的思想来操纵本机上的程序,这对于Linux在大规模集群中的应用非常重要。传统的Linux和某些低端嵌入式产品使用命令行的方式来控制,这与本文无关,不再介绍。12 Linux下的编程大多数Linux发行版支持几十种编程语言。对于Linux用户程序和Linux操作系统本身来说,最常用的工具是同样的GNU工具链,它包括GNU编译器集合(GNU Compiler Collection, GCC)和GNU build system。Linux内核本身就是使用GCC编译的。GCC支持的语言非常广泛,其中就包括Ada、C、C+、Java和Fortran,但最重要的是C。GCC的原名叫做GNU C Compiler,是Richard Stallman专门为C语言开发的自由编译器。本文中的程序也将完全基于C语言。大多数发行版也包括了对Perl、 Ruby、ython等动态语言的支持,还支持一些不大广泛使用的语言,这里的一个例子是通过Mono项目提供了对C#的支持。许多Java虚拟机和开发包也可以在Linux上使用,包括原版的Sun Microsystem JVM(HotSpot),以及IBM的J2SE RE,还有很多开源的项目例如Kaffe1。两个开发图形用户界面程序的主要框架是GNOME和KDE。这两个项目分别基于GTK和Qt widget toolkits。GTK和Qt widget toolkits也可以单独使用(本文中就是单独使用GTK,而不依赖于GNOME环境)。这两种框架都支持多种开发语言。2Linux中还有很多集成开发环境,如Anjuta、ode:Blocks、Ecpse、Kvelop、KnoDevelop、NBeans和Omnis Studio。但历史悠久的两大编辑器,将在本文中使用的Vim和另一种Emacs还是很流行。13 Makefile文件的编写 很多Windows程序员并不知道“Makefile”是什么东西,“万能的”IDE帮他们完成了程序的组织工作。如上文所说,Linux环境中也存在很多IDE和程序管理工具,但更多的人喜欢自己动手编写规则,让编译器按照自己的想法来编译,连接源程序。编译程序时,如果源程序只有一两个文件, 那么还可以使用特定的语言编译器进行编译和链接, 但是, 一旦源程序文件多达数十个, 甚至上百, 再使用语言编译器进行编译链接则是一件很繁琐的事。在这种情况下, 就需要使用make工具,而使用make工具时则需要编写Makefile(或makefile)的文件, 以指示编译器的工作。make的主要工作是读进一个文本文件Makefile。这个文件里主要是有关哪些文件( “target”目的文件)是从哪些别的文件( “dependencies”依靠文件)中产生的,用什么命令来进行这个产生过程。3有了这些信息,make会检查磁盘上的文件,如果目的文件的时间戳(该文件生成或被改动时的时间)比至少它的一个依靠文件旧的话,make就执行相应的命令,以便更新目的文件。(目的文件不一定是最后的可执行文件,它可以是任何一个文件。)。一个Makefile主要含有一系列的规则:target . : prerequisites . (Tab)commandtarget . : prerequisites .(Tab)command例如,考虑以下的Makefile :myprog : foo.o bar.ogcc foo.o bar.o -o myprogfoo.o : foo.c foo.h bar.hgcc -c foo.c -o foo.obar.o : bar.c bar.hgcc -c bar.c -o bar.o这是一个非常基本的Makefilemake从最上面开始,把上面第一个目的:“myprog”做为它的主要目标(一个它需要保证其总是最新的最终目标)。给出的规则说明只要文件 “myprog”比文件 “foo.o”或 “bar.o”中的任何一个旧,下一行的命令将会被执行。但是,在检查文件foo.o和bar.o的时间戳之前,它会往下查找那些把foo.o或 bar.o做为目标文件的规则。首先它找到的是关于foo.o的规则,该文件的依靠文件是foo.c, foo.h和bar.h。因为它从下面再找不到生成这些依靠文件的规则,它就开始检查磁盘上这些依靠文件的时间戳。如果这些文件中任何一个的时间戳比foo.o的新,命令 “gcc -o foo.o foo.c”将会执行,从而更新文件foo.o。接下来对文件bar.o做类似的检查,依赖文件在这里是文件bar.c和 bar.h 。现在,make 回到 “myprog”的规则。如果刚才那两个规则中的任何一个被执行,myprog就需要重建(因为其中一个 .o文件就会比 “myprog”新),因此连接命令将被执行。到这里,使用make工具来编译程序的优势就显而易见了:make程序完成了程序中最繁琐的检查步骤检查时间戳。源代码文件中的任何一个简单改变都会造成那个文件被重新编译(因为 .o文件依靠.c文件),进而可执行文件被重新连接(因为 .o文件被改变了)。其实这里最大的获益是当程序员改变一个header文件的时候,不再需要记住到底是哪个源码文件依靠它。因为所有的信息都存放在Makefile文件里,make程序会自然的帮助程序员重新编译所有那些依靠这个header文件,而其自身内容又改变了的源代码文件。如有需要,make将对生成的.o文件再重新进行连接。14 关于GTK+GTK+(本文中使用其另一个简要名称GTK)最初是GIMP的专用开发库,后来发展为类Unix系统下开发图形界面的应用程序的主流开发工具之一。GTK是自由软件,并且是GNU计划的一部分。GTK的许可协议是LGPL。4GTK实质上是一个面向对象的应用程序接口(API)。尽管完全用C写成的,但它是基于类和回调函数 (指向函数的指针) 的思想实现的。也提供了C+(gtkmm)、Perl、Ruby、Java和Python(PyGTK)绑定,其他的绑定有 Ada、D、Haskell、PHP 和所有的 .NET 编程语言。还有一个名为GLib 的第三个组件,包含一些标准函数的替代函数,以及一些处理链表等数据结构的函数等。这些替代函数被用来增强GTK 的可移植性,因为它们所实现的一些函数在其它 Unix 系统上未实现或不符合标准,比如 g_strerror()。另一些是对 libc的对应函数的增强,比如g_malloc() 具有增强的调试功能。在2.0版中,GLib 又加入这样一些新内容:构成 GTK类层次基础的类型系统 (type system),在 GTK 中广泛使用的信号系统,对各种不同平台的线程API进行抽象而得出一个线程API,以及一个加载模块的工具。Pango作为最后一个组件,GTK使用了它的库来处理国际化文字输出。与其他很多部件工具箱不同,GTK并不基于Xt。这一决策优劣互见:优点是GTK可以应用于其他系统,其灵活性也很强;而缺点就是它无法利用以传统方法为X11定制的X资源数据库。GTK提供不同的显示引擎使得最终用户可以定制外观和感觉。目前已经有一些可以模仿其他流行的平台或者工具箱(例如Windows 95、Motif、Qt或者NEXTSTEP)的引擎。Glade是GTK中常用的一个界面设计工具,但是它也包含了一种描述GUI界面的 XML 语言,它和 libglade 一起工作就可以直接使用GTK和GNOME控件;新的Glade-3不再直接支持生成编程语言源代码。由于本文界面很简单,因此将手工写出界面,而不使用Glade。15 GStreamer简介GStreame是一个创建流媒体应用程序的框架。其基本设计思想来自于俄勒冈研究生学院有关视频管道的创意, 同时也借鉴了DirectShow的设计思想。GStreame的程序开发框架使得编写任意类型的流媒体应用程序成为可能。在编写处理音频、视频或者两者都有的应用程序时,GStreame可以简化编程者的工作。GStreamer并不受限于音频和视频处理,它能够处理任意类型的数据流。管道设计的方法对于实际应用的滤波器几乎没有负荷,它甚至可以用来设计出对延时有很高要求的高端音频应用程序。5GStreamer最显著的用途是在构建一个播放器上。GStreamer已经支持很多格式的文件了,包括:MP3、Ogg/Vorbis、MPEG-1/2、AVI、Quicktime、mod等等。从这个角度看,GStreamer更象是一个播放器。但是它主要的优点却在于:它的可插入组件能够很方便的接入到任意的管道当中。这个优点使得利用GStreamer编写一个万能的可编辑音视频应用程序成为可能。本文将利用基本的Gstreamer功能,实现一个mp3播放器。由于Gstreamer的高度标准化,扩展支持其它媒体,如ogg等,非常容易。GStreamer框架是基于插件的, 有些插件中提供了各种各样的多媒体数字信号编解码器,也有些提供了其他的功能。所有的插件都能够被链接到任意的已经定义了的数据流管道中。GStreamer的管道能够被GUI编辑器编辑, 能够以XML文件来保存。这样的设计使得管道程序库的消耗变得非常少6。GStreamer核心库函数是一个处理插件、数据流和媒体操作的框架。GStreamer核心库还提供了一个API, 这个API是开放给程序员使用的,可以用于使用其他的插件来编写需要的应用程序。16 回调函数由于本程序中完全使用C语言,而GTK和Gstreamer中为了实现信号注册等功能,大量使用了C语言的回调函数。由于回调函数在其它语言中并不被广泛使用,因此,在此介绍一下回调函数。回调函数是一种非显式调用的函数,它是一种将自己的地址(函数指针) 传给别的函数来间接调用自己的编程方式。在使用回调函数时必须首先定义函数指针,然后才能使用函数指针实现回调。7也就是说,回调函数是一种将变量传给别的函数的函数。通常,它可以让系统函数调用用户函数,而不是平时我们使用的让用户函数调用系统函数。回调函数的实例程序:#include #include void *sig(int signum)printf(I gots me a signal of number %d!n, signum);int main(int argc, char *argv)signal(SIGUSR1,&sig);while(1);return 0;这里的while程序不做任何事情,只是用于拖延时间并等待用户发消息。对于类Unix系统而言,用户可以新开一个终端,输入“kill USR1 ”来给运行中的上述程序发消息。无论何时发送,callback函数总是会响应,并打印出”I gots me a signal of number 10”,这时因为SIGUSR1在Unix中被定义为10号信号。17 本程序的开发环境和使用到的一些工具因本人长期使用Ubuntu做桌面系统,本软件就是在最新的Ubuntu 8.10版下开发、调试的。Ubuntu是一个以桌面应用为主的Linux发行版,它基于Debian发行版和GNOME桌面环境,每6个月便有一个新版本问世。由于Ubuntu具有易于使用、安全、稳定、deb包管理方式可靠性高等优点,近年来已经取代了Redhat,成为Linux世界中最重要的发行版,占有率在30%以上。8.10的数字意义是08年10月推出的正式发行版,本人写作此文时,9.04版的正式版即将发布。此外,本程序中使用的Gcc编译器的版本号为4.3.2。GTK的版本号为2.0, Gstreamer为0.10.21。本程序中使用vim编辑器来书写程序代码。本程序中还使用了ctags和taglist插件。ctags是一种tag制作程序,用于配合vim编辑器使用。ctags可以制作程序中变量和函数名字的索引,配合vim,可以方便地跨越文件来查看函数或变量或结构体之类的定义,浏览大型程序时极为有效。taglist是一种配合ctags和vim使用的插件,它可以根据ctags生成的索引表,来列出当前文件中的主要变量和函数。2 编译环境的搭建和检测由于GTK和Gstreamer编译环境需要大量的库,通常需要首先更新或者安装一系列新版本的依赖程序或库。同时,由于软件包之间存在着依赖关系,对软件包的版本和安装顺序都有一定的要求,一般还需要对安装后的库进行一些必要的设置才能使用库,这对于初学者来说非常复杂。不过,Ubuntu系统中利用Synaptic软件包管理系统,只需要几条命令,Synaptic即会自动在配置好的源服务器里下载相关的软件包,并利用高效的依赖算法,自动解决繁杂的依赖性问题,自行搭建好开发环境,非常方便。由于本文的重点在于应用此开发环境进行开发,因此,本文只介绍在Ubuntu环境中使用命令进行搭建的方式,不再涉及其它搭建方式。21 基本编译环境的搭建刚装好的系统中已经有GCC了,但是这个GCC几乎什么文件都不能编译,因为它缺少一些必须的头文件。这里可以选择安装build-essential这个软件包来解决这个问题,方法是在Synaptic里面搜索build-essential或在终端中输入下面命令:sudo apt-get install build-essential安装完成后写一个C语言程序testc.c测试一下:#includeint main()printf(Hello Ubuntu!n);return 0;编译运行:$ gcc -Wall testc.c -o testc$ ./testc$ Hello Ubuntu!这样,基本开发环境就搭建成功了。22 安装GTK/GNOME编译环境要安装GTK环境,只需要安装一个libgtk2.0-dev软件包就可以了;而安装GNOME开发环境的话,则需要安装gnome-devel,由于它包含有GTK开发包,此时不再需要libgtk2.0-dev包。8在一般情况下,由于考虑到以后需要有一个Glade,并且还需要帮助文件,于是安装gnome-devel包和gnome-dev-doc包:sudo apt-get install gnome-devel gnome-dev-doc安装完成后也同样做个测试程序:#includevoid hello(GtkWidget *widget,gpointer data)g_print(Hello Ubuntu!n);gint delete_event(GtkWidget *widget,GdkEvent *event,gpointer data)g_print (delete event occurredn);return(TRUE);void destroy(GtkWidget *widget,gpointer data)gtk_main_quit();int main( int argc, char *argv )GtkWidget *window;GtkWidget *button;gtk_init (&argc, &argv);window=gtk_window_new (GTK_WINDOW_TOPLEVEL);gtk_signal_connect (GTK_OBJECT(window),delete_event,GTK_SIGNAL_FUNC(delete_event),NULL);gtk_signal_connect (GTK_OBJECT (window), destroy,GTK_SIGNAL_FUNC (destroy), NULL);gtk_container_set_border_width (GTK_CONTAINER (window), 10);button = gtk_button_new_with_label (Hello Ubuntu!);gtk_signal_connect (GTK_OBJECT (button), clicked,GTK_SIGNAL_FUNC (hello), NULL);gtk_signal_connect_object (GTK_OBJECT (button), clicked,GTK_SIGNAL_FUNC (gtk_widget_destroy),GTK_OBJECT (window);gtk_container_add (GTK_CONTAINER (window), button);gtk_widget_show (button);gtk_widget_show (window); /*显示一个窗口*/gtk_main(); /*进入主循环*/return(0);用下面命令编译运行:$ gcc gtkhello.c -o gtktest pkg-config -cflags -libs gtk+-2.0$ ./gtktest此时会显示一个带有一个按钮的窗口,点击按钮以后窗口关闭,命令行显示Hello Ubuntu!23 安装GStreamer编译环境在Ubuntu中构建GStreamer开发环境同样非常简单,使用下面命令安装GStreamer就可以了。$ sudo apt-get install gstreamer0.10-tools gstreamer0.10-x gstreamer0.10-plugins-base gstreamer0.10-plugins-good gstreamer0.10-plugins-ugly gstreamer0.10-plugins-bad gstreamer0.10-ffmpeg gstreamer0.10-alsa gstreamer0.10-schroedinger gstreamer0.10-pulseaudio本段代码用于测试:#include int main (int argc, char *argv) const gchar *nano_str; guint major, minor, micro, nano; gst_init (&argc, &argv); gst_version (&major, &minor, µ, &nano); if (nano = 1)nano_str = “(CVS)”; else if (nano = 2) nano_str = “(Prerelease)”; else nano_str = “”; printf (“This program is linked against GStreamer %d.%d.%d %sn”, major, minor, micro, nano_str); return 0;用以下命令进行编译:$ gcc Wall mu.c o gstestpkg-config gstreamer-0.10 cflags libs$ ./gstest成功则输出:“This program is linked against GStreamer 0.10.21”。至此,编译环境搭建完毕。3 程序的设计目标和分析31 程序设计目标程序设计目标是:结合GTK和GStreamer实现一个图形界面mp3音频播放器。具体目标如下:1) 能够方便地选择本机上的一个mp3文件进行播放。选择mp3文件时,不需要有键盘输入操作。2) 播放过程中可以暂停,暂停后可以从暂停处再次播放。播放过程中可以停止,按下播放按钮后,可以再次从开头播放本文件。本程序提供“快进”、“快退”按钮,分别跳到后方5%处和前方5%处,播放和暂停状态都可以快进快退,并保持当前状态不变。3) 播放、暂停、或停止状态中,都可以选择其它mp3文件代替当前mp3文件进行播放。4) 本程序中要有一个滚动条来显示当前的mp3文件播放位置,拖动滚动条,可以调节mp3文件的播放位置。5) 在面板上显示mp3文件当前播放的时间和mp3文件的名字。播放时间随时刷新,配合好前面的播放调节操作。6) 提供“帮助”,“关于”等菜单按钮。退出按钮要绝对有效,能够完美地结束整个程序,不在内存中留下垃圾。7) 界面尽量美观,程序运行时不要出现异常。8) 程序能在所有使用Gnome的Linux发行版上安装使用。32 需求分析用GTK和GStreamer实现一个简单的mp3播放器并不是一件困难。但要搞清楚具体执行逻辑,使写出的程序不出现难以解决的逻辑错误而导致最后的返工,还是需要事先认真规划好的。图形界面mp3播放器。根据常识来看,打开软件后,会出现图形界面,然后点击图形界面,选择mp3文件,点击开始,即可播放了。图形界面出现后,要想让其响应用户的点击,就必然要有一个类似服务器的进程来执行接受用户命令的任务,GTK中的gtk_main函数可以担当这个角色,因此,本文将围绕这个函数来进行程序的设计。程序规划流程图如图3-1所示:程序开始执行用GTK创建用户界面和按钮、菜单等控件响应用户退出程序的要求,清理、退出为按钮、菜单、等控件注册信号gtk_main()主循环,等待信号发生并处理图3-1 程序规划流程图无论在什么平台下,无论用什么开发工具,GUI应用程序的基本开发方法都是相似的。开发人员都要编写两方面的代码,即应用于实现图形界面的代码和用于实现程序运行的代码,然后再将这两部分的代码结合起来,本程序也不例外。用GTK绘制完用户界面后,要给控件加上信号,信号中附上自己编写的函数地址。然后,操纵控件时,比如按下按钮后就会产生信号,gtk_main()循环会捕捉这个信号,按照信号注册时附上的函数地址调用特定的函数:例如播放音频的函数。这样,程序的大体构架就清楚了。即,程序由事件信号驱动,接收到响应信号时调用预先编写好的处理函数进行处理。4 程序的详细设计及编码41 程序文件的组织为了程序逻辑的清晰着想,不能把一个大程序中的所有内容放到一个文件里,否则,当程序增大到一定程度时修改和调试将变得极为困难。再加之前面需求分析中已经提到的,编写GUI程序时,通常的做法是界面和后台分别编码,这样做简单且逻辑清晰。因此可以在main函数中调用绘制界面的函数,并分别注册上信号,用gtk_main()循环完成函数调度的工作。但绘制界面如果全部都在main函数中完成的话,程序代码会显得非常混乱,因此可以把绘制界面的工作分成很多步来完成,main函数调用每一步中相应的绘制函数。当然可以把这些绘制函数跟main函数都一起放到main.c文件中,但这样做的话,还是不够清晰。不妨新建一个gui.c文件,将完成图形绘制以及注册信号工作的函数集中放到里面。接着考虑后台处理函数,很自然的,把这些函数都放到back.c文件中。综上所述,本程序将建立main.c、gui.c、back.c三个头文件。由于函数之间具有相互调用关系,如果要将这三个.c文件结合起来,就需要用到头文件。因而,将按照程序的需要,选择性地建立main.h、gui.h、back.h头文件,在其中放入对应的.c文件中非静态函数和变量的声明。42 main.c文件文件的的开始,程序先引入GTK和GStreamer工具包中所有类和函数的声明:#include #include extern GtkWidget *gui();我在随后的gui.c文件中将会编写一个生成图形界面的gui()函数。上面将其它文件中的函数导入时,使用了extern关键字,让程序更规范。接着声明 window变量:GtkWidget *window;GtkWidget类声明了一个名字为window的指针变量。由于gui.c中的函数要使用本变量,这里将其放到main函数外面,使其具有全局作用域。同时,考虑到main.c文件中只有一个main函数和一个全局变量,我决定不再编写main.h头文件,如果其它文件需要使用window变量的,显式的将所需变量引入即可。下面的是main()函数:int main(int argc, char *argv)main函数中,程序首先分别对GTK和GStreamer进行初始化,初始化会设置函数库并处理命令行参数中的GTK和GStreamer知道的参数。由于本程序中用不到这些参数,因此,这里只是起到初始化的作用。9接着,初始化gtk和gst:gtk_init(&argc, &argv);gst_init(&argc, &argv);窗口本身是由gtk_window_new()创建的:window = gtk_window_new(GTK_WINDOW_TOPLEVEL);该函数是一个对象构造器,它返回一个指向新GtkWindow对象的指针。命名约定在这里非常重要,因为GTK中的所有对象构造器和方法都要遵循它名字的第一部分是类名,这里是GtkWindow(对于函数名来说,将它写为gtk_window,以将它和类本身的数据类型区分开来),然后是方法名。gtk_window_new()接受一个参数,这个参数是一个常量,它指定了要创建的窗口类型。GTK_WINDOW_TOPLEVEL是一个正常的应用程序窗口,它可以通过窗口管理器关闭、最小化和调整大小。调用gst_container_add()函数:gtk_container_add (GTK_CONTAINER (window), gui();随后编写的gui()函数将生成并返回window内的各个控件的集合,程序将window作为一个容器,把gui()生成的图形界面加入进来,然后显示窗口。要注意,GTK生成的窗口和控件默认都是不显示的,程序必须调用gtk_widget_show函数来显示它:gtk_widget_show(window);gtk_main();GTK应用程序采用事件驱动机制,在完成用户界面创建后进入gtk_main()主循环,由此GTK 接管了控制权,然后在主循环中循环地监听事件和信号的发生。当捕获事件或信号后,则将控制权传递至所注册的信号事件处理程序进行处理,然后根据此程序选择返回或者退出GTK应用程序。后面将用到的函数gtk_main_quit用来结束主事件循环,即退出GTK程序的运行。至此,main.c文件就结束了。显然,它的脉络很清晰,符合需求分析中所作的程序流程图的规划。以下就要分别对图形界面和后台进行编程了。43 图形界面的结构现在程序有了一个窗口(window变量),但是,如果没有其他构件来提供有用的用户界面,它是没有什么用处的。GTK+中的窗口是GtkBin的子类,它是一种只能包含一个子构件的容器对象。这好像并不是特别有用,但GTK+还提供了各种可以容纳多个构件的GtkBin子类。因此,GTK+中的窗口布局总是在一个GtkWindow中添加一个多构件容器来构成的。Error! Reference source not found.这些容器中最有用的是GtkVBox、GtkHBox和GtkTable。GtkVBox允许任意数量的构件垂直叠放。GtkHBox的功能相同,但提供的是水平排列。GtkTable是上述两者的结合,它允许构件在一个灵活的网格中进行排放。10这三种布局构件几乎提供了所有必要的布局功能。需要注意的是,GTK+很少处理对象的绝对位置或大小容器和其中的构件将调整大小以适应可用空间。不过可以改变这类大小调整的一些约束以获得所需的效果,如果确实需要精确的像素布局,那么GtkFixed可作为最后的选择。应该首先选择灵活的盒状模型布局(Box),因为它更容易使用。最后,mp3播放器的最终效果如图4-1所示图4-1 播放器的最终效果上图显示了在装载文件进行播放之前的音乐播放器窗口。从上往下,依次是菜单栏,用于显示文件名的标签,五个控制播放的按钮,下面是显示播放经过时间的标签,最后是一个在当前文件中进行搜寻的滑动条。整个图形界面的布局如图4-2所示vbox(全部项目放到这个垂直盒子里)title_label(mp3文件名)time_label(时间标签)time_label(播放时间)bar(滚动条)menubox(装有菜单的水平盒子)File(文件菜单) Help(帮助菜单)buttonbox(装有按钮的水平盒子)图4-2 图形界面的布局以上显示的是垂直盒子(vbox)及其内部控件的布局,gui()函数返回这个垂直盒子,正如在main函数中看到的那样,把这个垂直盒子放到了window窗口中,整个图形界面就完成了。44 PLAY按钮关于构件盒子里的一个个控件的的方法,以“PLAY”按钮为例进行说明。首先,先声明垂直盒子的变量:GtkWidget *vbox;其次,再创造按钮盒子变量:GtkWidget *buttonbox;再到PLAY按钮变量:GtkWidget *playbutton;分别为它们赋值:vbox = gtk_vbox_new(FALSE, 0);buttonbox = gtk_hbox_new(FALSE, 0);playbutton = gtk_button_new_with_label(PLAY);gtk_vbox_new参数的作用是调整构件在盒子中的摆放方式。第一个参数指明组装盒中的构件是否都必须具有相同的高度,一个false值表示构件可能根据它们的需求有不同的高度。第二个参数指明在构件之间的以像素为单位的间距,把它设置为0。gtk_hbox_new中的参数与vbox中的类似。gtk_button_new_with_label函数返回一个带有文字标签的按钮,本按钮上的文字是“PLAY”。可是,单有“PLAY”标签并不能让这个按钮发出播放的命令,程序还要为它注册上信号处理函数,让它既有名又有实:g_signal_connect(G_OBJECT(playbutton), clicked, G_CALLBACK(play_pressed), NULL);信号处理函数即play_pressed函数。调用本函数完成信号向gtk_main()的注册,每次“click”鼠标来点击“playbutton”以后,gtk_main()会自动调用play_pressed函数。g_signal_connect的第一个参数是要发出信号的构件,第二个参数是你想要连接的信号的名称,第三个参数是信号被捕获时所要调用的函数,第四个参数是你想传递给这个函数的数据。由于不需要向play_pressed函数传数据,这里忽略了第四个参数。G_OBJECT()和G_CALLBACK()都是宏,被定义为具有强制类型转换的功能。程序把play_pressed的函数放到back.c文件中。函数的功能调用链接GStreamer插件的函数,进行mp3文件的播放。函数原型如下:void play_pressed();现在重新回到这个按钮上来。程序刚刚为它添加了信号处理函数,但是,如何做到将
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《生活科学启蒙课堂|发现身边的吸铁石知识》
- MASH治疗进展与个体化管理2026
- 精密产业园片区排水管建设项目可行性研究报告模板拿地申报
- 2026版届高三数学高考三模模拟试卷(含参考答案解析)全流程SOP与执行检查表轻量版模板
- 2026年开封市顺河回族区网格员招聘考试备考试题及答案详解
- 2026年伊春市金山屯区网格员招聘考试备考试题及答案详解
- 2026年鸡西市滴道区网格员招聘笔试参考试题及答案详解
- 2026年河南省开封市社区工作者招聘考试备考题库及答案详解
- 医药领域腐败问题集中整治工作总结
- 2026年哈尔滨市道里区网格员招聘考试备考试题及答案详解
- 2025老年人能力评估师题库及答案
- 医院安全生产考核细则
- 中国软件行业协会:2025中国软件行业基准数据报告 SSM-BK-202509
- 医院招聘检验试题及答案
- 企业资料档案管理制度化模板
- 2023-2024学年广东省深圳市高一(下)期末化学试题及答案
- GB/T 4026-2025人机界面标志标识的基本和安全规则设备端子、导体终端和导体的标识
- 临期药品药店社区服务2025年拓展方案报告
- 体检流程标准化步骤
- CJ/T 490-2016燃气用具连接用金属包覆软管
- 自考 00018 计算机应用基础
评论
0/150
提交评论