使用wxWidgets进行跨平台的C++开发

本文为原创,如需转载,请注明作者和出处,谢谢!



本文阐述了wxWidgets的由来,以及从wxWidgets的特点出发,说明了选择wxWidgets给我们带来的好处,并且通过一个典型的例子讨论了如何在C++中使用wxWidgets开发跨平台的软件。

什么是wxWidgets

wxWidgets是一个跨平台的软件开发包。它诞生于1992年,最初的名子是wxWindows,但由于Microsoft的抗议,在2004年改名为wxWidgets。它最初是被设计成跨平台的GUI软件开发包,但后来随着越来越多的人参与进来,为wxWidgets加入了许多非GUI的功能,如多线程(MultiThread)、网络(Network)等。并且从最初的只支持C++语言,逐渐发展成为支持数种语言(如Python、Perl、C#、Basic等)。因此,现在的wxWidgets已经不再是单纯的跨平台的GUI软件开发包,而是一个可以支持多种操作系统平台的能够在多种语言中使用的通用跨平台软件开发包。

由于wxWidgets最开始是为C++而设计的,因此,本文主要讨论了wxWidgets在C++中的使用。

为什么选择wxWidgets

目前支持C++的软件开发包非常多,比较有名的除了wxWidgets外,还有一些其它的软件开发包,如MFC、QT、ACE等。即然有这么多开发包,那么我们为什么要使用wxWidgets呢?在给出答案之前,让我们首先来看一看上述的三种软件开发包的特性。

1.      
MFC

MFC是Microsoft提供的软件开发包。MFC虽然十分强大,但它只能运行在Windows下运行。而且它是收费的。

2.  QT

QT是由Trolltech 公司开发的一套跨平台软件开发包。它和wxWidgets类似,但是QT只在linux下免费,而在Windows或Unix下使用QT要向Trolltech公司支付版权费。

3.  ACE

ACE虽然是免费开源的,但是它没有提供GUI功能。

    从以上三个软件开发包可以看出,它们虽然有各自的优势,但是它们或多或少地都会使开发受到限制。而使用wxWidgets将不会有以上所述的问题。wxWidgets和MFC、QT、
ACE的特性对比如表1所示。

表1: wxWidgets和MFC、QT、ACE的特性对比表

    注:其中免费中的“是/否”代表QT在linux平台上的Free
Edition是免费的,而在windows和unix下使用QT是收费的。而开源中的“是/否”代表QT有一个基于GPL的开源版本,但要进行商业开发,需要使用它的商业版本。

使用wxWidgets编写程序

学习一种编程语言的最好方法就是用它去编写程序,学习wxWidgets也不例外。由于wxWidgets的主要功能是实现跨平台的GUI,因此,本文主要从GUI入手,讨论wxWidgets在C++中如何编写跨平台的应用程序

1.  应用程序类的建立

使用wxWidgets建立系统需要一个类来描述整个应用程序。这个类必须从wxApp类继承。

class MyApp : public wxApp   //应用程序类
{
public:
    virtual bool OnInit(); // 在应用程序启动时调用,如果返回false,退出应用程序
};

这个类只覆盖了wxApp的一个虚方法OnInit。可以用这个方法在程序启动时做一些验证,如果验证失败,可以通过返回false退出应用程序。当然,由于这个函数是应用程序的入口点,所以建立主窗体的工作要在这个函数中完成。

2. 建立窗体类

    wxWidgets中关于窗体的类很多,如果要建立一般窗体的话,可以从wxFrame继承。

class MyFrame : public wxFrame //窗体类
{
public:
    MyFrame(const wxString& title); // 窗体的构造函数
};

3. 向窗体中加入控件

    在本文中向这个窗体加入了一个菜单条(Menu Bar)、一个状态条、一个Panel和一个按钮。一般我们会在主窗体的构造函数中加入这些控件。

MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title)
{
    wxMenu *fileMenu = new wxMenu;  // 建立“文件”菜单 
    wxMenu *helpMenu = new wxMenu; // 建立“帮助”菜单
    // 向菜单中添加子项
    helpMenu->Append(wxID_ABOUT, _T("关于/tF1"), _T("显示关于对话框"));
    fileMenu->Append(wxID_EXIT, _T("退出/tAlt-X"), _T("退出应用程序"));
    wxMenuBar *menuBar = new wxMenuBar();  // 建立一个菜单条
    menuBar->Append(fileMenu, _T("文件"));  //将“文件”菜单加入到菜单条
    menuBar->Append(helpMenu, _T("帮助"));  //将“帮助”菜单加入到菜单条
    SetMenuBar(menuBar);  //将菜单条放到窗体上
    wxPanel *panel = new wxPanel(this);   //建立一个Panel
    wxButton *button = new wxButton(panel, wxID_ABOUT, "关于", wxPoint(20, 20), wxSize(50, 30));  //建立一个Button
    CreateStatusBar(2);  //建立一个两栏的状态栏
    SetStatusText(_T("欢迎使用wxWidgets!"));  //设置状态栏的文本

    在数组sample_xpm中描述了sample.ico的属性和图标本身。如X代表红色; o代表黄色等。然后在源程序中通过include
“sample.xpm”引用这个资源文件。要想从这个资源文件中装载图标。可使用SetIcon(wxICON(sample)); wxICON读取资源文件,而SetIcon将这个图标设置为frame的标题栏图标。要想将ico文件转换为这种资源文件,可使用一个免费软件XnView进行转换。

5. 显示主窗体

    显示主窗体非常简单,只需要将上面建立的MyFrame类实例化,并调用wxFrame的Show方法显示即可。这些代码可以写在MyApp类的OnInit方法中。

bool MyApp::OnInit()
{
    //建立MyFrame类的实例
    MyFrame *frame = new MyFrame(_T("第一个wxWidgets程序"));
    frame->Show(true);  //显示主窗体
    return true;  //必须返回true,否则应用程序将退出
}

在以上代码中Show方法有一个参数,如果为true,则以模式窗口的形式显示,否则以非模式窗口的形式显示。

6. 向窗体中加入事件

到目前为止,这个程序的界面已经完成了,但还未响应任何事件,下面就详细阐述如何向这个应用程序中加入事件代码。
    对于事件来说,一般都会由两部分组成。

(1)调用事件部分

当程序发生某个动作时,如点击按钮;选中某个控件,可能需要执行一段代码。而这段代码一般是由系统负责调用的,也就是说系统通过事件函数指针调用相应的代码。

(2)事件函数本身

    事件函数与普通函数一样,只不过它是在发生了事件之后,由系统调用的。

在wxWidgets中是通过事件哈希表(Event Hash Table)来进行事件处理的,即将相应的事件函数指针保存在一个哈希表中,然后当事件发生时,从这个哈希表中找到相应的事件函数指针,然后通过函数指针调用函数。在使用事件哈希表之前,必须定义它。由于定义哈希表非常复杂,而且每个需要处理事件的类都需要同样的代码,因此,wxWidgets为此定义了一个宏DECLARE_EVENT_TABLE()来定义哈希表。可将这个宏写在MyFrame类的任何位置。它相当于将以下语句放到了MyFrame类中。

    private:
       static const wxEventTableEntry sm_eventTableEntries[]; 
    protected: 
        static const wxEventTable  sm_eventTable; 
        virtual const wxEventTable*  GetEventTable() const; 
        static wxEventHashTable  sm_eventHashTable;
        virtual wxEventHashTable&  GetEventHashTable() const;

其中静态数组变量sm_eventTableEntries保存了MyFrame类中的所有的事件信息。

上面的代码声明了处理事件哈希表的一些方法,即然声明了,就得实现。由于实现代码也都一样,因此,wxWidgets也为实现这些方法定义了一组宏。实现这些方法的宏如下所示。

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(wxID_EXIT,  MyFrame::OnQuit)
    EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
    EVT_BUTTON(wxID_ABOUT, MyFrame::OnAbout)
END_EVENT_TABLE()

    其中BEGIN_EVENT_TABLE(…)实现了上面定义的方法,以及初始化了静态变量sm_eventTable。后面两个EVT_MENU和一个EVT_BUTTON宏初始化了静态变量sm_eventTableEntries,即将这两个事件函数的指针(button和about菜单使用一个事件函数OnAbout)和控件ID保存在sm_eventTableEntries中,最后的END_EVENT_TABLE()宏做为一个空的事件函数指针赋给了sm_eventTableEntries,这有些象C语言中处理字符串,将最后一个字符赋为’"0’,这样就可以知道哪是结尾了。
    向窗体中加入事件的最后一步是声明和实现事件函数。在本例中声明了两个事件函数。

void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);

可以将这两个函数声明放到MyFrame中的任何位置。下面是它们的实现代码。

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{  
    Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
    wxString msg;
    msg.Printf( _T("这是一个关于对话框的例子./n")
                _T("欢迎使用 %s"), wxVERSION_STRING);
    wxMessageBox(msg, _T("¹关于"), wxOK | wxICON_INFORMATION, this);
}

其中OnQuit函数调用Close(true)关闭MyFrame,由于MyFrame是主窗体,因此,在MyFrame关闭后,应用程序也随之关闭了。OnAbout使用wxMessageBox函数弹出一个信息对话框。

7.  运行程序

到目前为止,这个程序的代码已经基本完成了,但是在前面曾说过,MyApp中的OnInit方法在应用程序启动时执行,那么是谁调用了OnInit方法呢?答案当然是wxWidgets。wxWidgets为了调用这个方法,提供了一个宏IMPLEMENT_APP(…),这个宏有一个参数,需要将MyApp做为参数传入。即IMPLEMENT_APP(MyApp)。这个宏相当于一个WinMain函数(和控制台程序的main函数类似),即在WinMain函数中调用了MyApp中的OnInit函数。在加入这个宏后,就可使用一个C++编译器将以上的源程序编译生成exe文件了。应用程序的界面如图1、图2所示。

图1 Windows下的程序界面

图2  Linux下的程序界面

注:在windows下使用的wxWidgets版本是wxWidgets2.6.2,在linux下使用的wxWidgets版本号是wxWidgets2.6.3,因此,在windows和linux下的wxVERSION_STRING值不一样。

wxWidgets的优势和不足

通过上面的介绍,相信读者已经对如何使用wxWidgets编写GUI程序有了一定的了解。wxWidgets在开发跨平台的软件上有着许多其它软件开发包不具备的优势,下面就总结一下wxWidgets所具有的优势。

    1.  跨平台
    wxWidgets支持非常多的操作系统平台,如Windows、Linux、Unix等。

2.  丰富的组件

wxWidgets拥有上百个组件可供用户选择。有了这些组件,将会给我们带来更加丰富的用户体验。

3. 支持多种语言

wxWidgets不仅可以在C++中使用,而且也可以在其它语言中使用,这些语言包括python、perl、c#等。

4.      
使用本地控制

从上面给出的两个应用程序界面可以看出,在Windows和Linux下运行这个应用程序保持了各自的风格。这是因为wxWidgets采用了本地的API,而不象其它的跨平台库去模拟它们。因此,使用wxWidgets开发和在Windows下使用Win32
API或在Linux下使用GTK开发没有什么区别。

5. 免费开源

这个世界上免费的开发包很多,强大的开发包也很多,当然,开源的开发包就更多了。但是要想同时满足这三点:免费、开源、强大,又同时具有本地程序一样的性能,恐怕wxWidgets是唯一的选择,至少是最佳的选择。

相信上面关于wxWidgets的5个优势已经足以成为我们选择它的理由了。也就是说,如果选择wxWidgets,不仅可以获得强大的功能、卓越的性能,而且您不必为此付一分钱。当然,人无完人、物无完物。wxWidgets也并不是没有缺点。下面就说一下wxWidgets的不足之处。

1. IDE支持不够

对于wxWidgets来说,最大的优点也就是它最大的缺点。由于wxWidgets所提供的组件很多,但到现在为止还没有一个强大的IDE来支持它,这将给大型系统的开发带来麻烦。

2. 对双字节字符的支持不理想

wxWidgets中的有些组件,如xml组件,无法识别双字节字符,如汉字会被认为是非法字符而无法装载xml文档。

综合上述,wxWidgets从总体上来说还是一个非常强大的跨平台软件开发包。如果您没有足够的资金来购买商业的软件开发包,也许wxWidgets是最好的选择。虽然wxWidgets也有一些不足,但这并不能阻碍wxWidgets的发展。wxWidgets的功能还很多,由于篇幅所限,本文只能从一个简单的例子来讨论如何用wxWidgets来开发一个跨平台的GUI程序,如果读者对wxWidgets感性趣,可以访问http://www.wxWidgets.org获得更多的信息。

    要在Linux下使用Eclipse开发wxWidgets程序,请读者参阅《快速配置Linux + Eclipse + wxWidgets开发环境》

国内最棒的Google Android技术社区(eoeandroid),欢迎访问!

《银河系列原创教程》发布

《Java Web开发速学宝典》出版,欢迎定购

时间: 2024-10-28 12:38:03

使用wxWidgets进行跨平台的C++开发的相关文章

前端开发者的跨平台移动应用开发策略及工具

愉悦的周五,早些回到家,冲澡吃饭照顾猫咪家务完毕已然超过九点的样子.登录博客后台,进入编辑页面,才觉得些许轻松安逸.不坏,一天里能有这么一会沉浸在这样的感觉里,足够了. 在之前的一篇文章中,我们曾经讨论过,对于交互和视觉设计相关职能的从业人员来说,从传统Web行业向移动应用领域转型的过程中需要学习和注意的问题.这篇文章中提到过"混合型应用"的概念,以及与之相关的两本开发指导书籍.今天这篇文章的英文原文,就是来自这两本书的作者--移动应用开发者Jonathan Stark. 本文中,他将

9大跨平台移动 App 开发工具推荐

如今,移动应用开发已经变得越来越重要,开发人员面临最大的挑战之一就是在多个平台上运行应用程序.最新的应用程序代码支持"一次编写,到处运行"(WORA)的概念,即只要在一个平台上编写代码一次,就可以在多个平台运行.本文我们将为大家介绍 9 个优秀的移动 App 开发工具,帮你在短时间内设计出最前沿.最高效的应用. 9.移动应用开发工具 Codename One Codename One是一个针对移动应用开发者的.开源的.跨平台的Java工具,旨在帮助Java开发者通过单一代码库来针对所有

跨平台移动应用开发引擎CrossApp推出正式版V0.3.0

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 跨平台移动应用开发引擎CrossApp终于推出了正式版本V0.3.0, 同时对外放出了与原生应用的详细横评数据,在数据中看,CrossApp已经与原生性能近似,官方也正是对外宣称,开发者可以开始免费使用CrossApp的正式版本来进行移动端商业产品的开发了. 在CrossApp的正式版本推出同时,官方也正是对外推出了CrossApp-Desi

bitbucket+Sublime Text 2配置跨平台的nodejs开发环境

由于我这个应用会在三台电脑上开发,winXP,win7,mac,所以开发环境要考虑两个问题,一是同步,而是软件差异性,同步我采用git的方式把代码托管到 https://bitbucket.org/,换电脑前先push.地址:https://bitbucket.org/voidmansun/sc_nodejs 软件方面我建议nodejs的ide用Sublime Text 2,为什么要用这个呢,我主要用的他下面的特性:代码高亮,自动补全,丰富的插件,跨平台 如此神器,肯定要用下试试,下载地址在这里

ElectroTank发布跨平台服务器可开发在线游戏

(编译/Wendy)在当地时间10月8日举行的首届游戏开发者在线游戏选择奖(GDC Online)典礼上,服务器制造商ElectroTank发布了Electroserver ES5,支持跨平台(包括Falsh,Unity3D,iOS和Android平台)多人在线游戏的开发. 最新版本的服务器在之前的版本上做了改进,之前的版本只支持Flash开发,现在支持跨平台多用户同时连接. 新版本的新特性包括一个为高分组速率传输而设的用户数据报(UDP)协议,增强了安全和反黑客技术,和一个消除同时连接数限制的

NativeScript —— 跨平台移动端开发

NativeScript 可以使用 Javascript,CSS, XML 创建真正的 Native 跨平台应用,支持 iOS Android,NativeScript 将您的跨平台代码翻译成目标平台的代码. UI 使用 XML 描述,CSS 样式,在编译时将 UI 转化成本地原生代码,最终得到正在的 Native 原生应用. 文章转载自 开源中国社区 [http://www.oschina.net]

快速配置Linux + Eclipse + wxWidgets开发环境

本文为原创,如需转载,请注明作者和出处,谢谢!     wxWidgets是一个跨平台的C++开发库,与MFC类似.不过配置起来比较麻烦,如果在Linux下使用Eclipse来开发基于wxWidgets的应用程序需要进行一系列的配置,如设置include路径.library路径等.但我们可以使用一个简单的方法来快速配置wxWidgets.     在wxWidgets发行发中有很多例子,随便编译一个例子(执行make命令),就会在终端中看到生成.o和可执行文件的完整命令.如果要编译自己写的程序,

跨平台的应用开发工具和前端开发工具

文章描述:前端开发者的跨平台移动应用开发策略及工具. 愉悦的周五,早些回到家,冲澡吃饭照顾猫咪家务完毕已然超过九点的样子.登录博客后台,进入编辑页面,才觉得些许轻松安逸.不坏,一天里能有这么一会沉浸在这样的感觉里,足够了. 在之前的一篇文章中,我们曾经讨论过,对于交互和视觉设计相关职能的从业人员来说,从传统Web行业向移动应用领域转型的过程中需要学习和注意的问题.这篇文章中提到过"混合型应用"的概念,以及与之相关的两本开发指导书籍.今天这篇文章的英文原文,就是来自这两本书的作者--移动

英特尔设立1亿美元基金 推动跨平台应用开发

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp; 北京时间11月16日消息,据国外媒体报道,英特尔旗下风险投资机构Intel Capital设立一只规模达1亿美元的基金,投资开发跨平台应用的创业公司. 英特尔高管蕾妮·詹姆士(Renee James)表示,设立该基金的目的是推动包括超级本在内的多种设备的应用开发,使开发者能更方便地在多种平台上发布应用.英特尔在加利福尼亚州亨廷顿海滩市举行的全球峰会上公布了这一消息.