wxWidgets 跨平台C++开发

2024-02-10 06:18
文章标签 c++ 开发 跨平台 wxwidgets

本文主要是介绍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开发环境

这篇关于wxWidgets 跨平台C++开发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/696344

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名