【wxWidgets 教程】HelloWorld 程序详细介绍(二)

这篇具有很好参考价值的文章主要介绍了【wxWidgets 教程】HelloWorld 程序详细介绍(二)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、代码

在上一篇,我已经把 HelloWorld 的代码写了出来,这里为了方便介绍,我重新贴一遍:

#include <wx/wxprec.h>

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

class MyFrame : public wxFrame
{
public:
    explicit MyFrame(const wxString &title)
      : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
    {
        // 创建一个面板
        auto *panel = new wxPanel(this, wxID_ANY);

        // 创建一个按钮
        auto *button = new wxButton(panel, wxID_ANY, wxT("Click me!"),
                                    wxPoint(60, 40), wxSize(100, 30));

        // 绑定按钮点击事件
        button->Bind(wxEVT_BUTTON, &MyFrame::OnButtonClicked, this);
    }

private:
    void OnButtonClicked(wxCommandEvent &event)
    {
        wxUnusedVar(event);
        wxMessageBox(wxT("Hello, wxWidgets!"), wxT("Hello"), wxOK | wxICON_INFORMATION);
    }

wxDECLARE_EVENT_TABLE();
};

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_BUTTON(wxID_ANY, MyFrame::OnButtonClicked)
wxEND_EVENT_TABLE()

class MyApp : public wxApp
{
public:
    virtual bool OnInit()
    {
        auto *frame = new MyFrame(wxT("Hello wxWidgets!"));
        frame->Show(true);
        return true;
    }
};

wxIMPLEMENT_APP(MyApp); // NOLINT

二、详细介绍

1. 头文件包含部分

#include <wx/wxprec.h>

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

其实不想折腾,可以直接写成这样:

#include <wx/wx.h>

它们的主要区别在于“预编译”。启用预编译头可以提高编译速度,但在某些情况下可能导致额外的配置兼容性问题(虽然这种情况目前我没遇到)。如果你不确定是否需要预编译头,那么直接包含 wx/wx.h 是一个更简单的选择。

2. 程序入口

我们直接跳转到代码段的最底部,看到这句:

wxIMPLEMENT_APP(MyApp); // NOLINT

这是 wxWidgets 中用于定义应用程序入口点的宏。这个宏会自动生成一个 main 函数(在 Windows 上为 WinMain 函数),该宏定义会创建应用程序类的实例并启动程序的事件循环

MyApp 是自定义的应用程序类,它必须从 wxApp 类派生(代码中有体现,稍后会介绍)。wxIMPLEMENT_APP() 宏将 MyApp 与库中的实际入口点关联起来。这样,当程序启动时,wxWidgets 便知道如何创建应用程序类的实例并调用 OnInit() 方法来初始化应用程序

那么我们可能会有个疑问,wxWidgets 为什么要隐藏 main 函数呢?我认为无非就两个原因:

  • 跨平台兼容性:wxWidgets 是一个跨平台的库,可以在多种操作系统(如 Windows、macOS 和 Linux)上运行。不同的平台可能有不同的应用程序入口点要求。隐藏 main 函数,让 wxWidgets 来处理平台相关的差异,使得我们的应用程序代码保持跨平台兼容
  • 简化程序开发:隐藏 main 函数,wxWidgets 将会帮助我们处理平台底层的细节,这样我们开发时就可以专注于实现自定义的应用程序类和其他功能,而不需要关心平台相关的细节

当然,有些小伙伴还是想自己操纵 main 函数(例如我),这完全可以,而且 wxWidgets 也没有难为我们,下面是自定义 main 函数的例子:

  • Windows
wxIMPLEMENT_APP_NO_MAIN(MyApp);  // NOLINT

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wxCmdLineArgType lpCmdLine, int nCmdShow)
{
	return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
  • Linux
wxIMPLEMENT_APP_NO_MAIN(MyApp);  // NOLINT

int main(int argc, char **argv)
{
    return wxEntry(argc, argv);
}
  • macOS

    没钱买电脑……我猜跟 Linux 的写法是一样的。

上述代码中,我们使用 wxIMPLEMENT_APP_NO_MAIN 替换了原来的 wxIMPLEMENT_APP。这种写法既保留了 wxWidgets 为我们做的一些预处理工作,又可以自定义 main 函数,是我的理想化答案。

3. MyAPP 应用程序类

顾名思义,这是应用程序的入口类。它本身并没有创建窗口,它的指责只是创建一个应用程序,并且让它运行起来。一个应用程序,它可能有一个或多个窗口,但它只有一个程序入口(如果用“每个程序一个窗口”的方式来实现多窗口,我想你可能要用到进程间通信)。这个示例中的 MyAPP 定义如下:

class MyApp : public wxApp
{
public:
    virtual bool OnInit()
    {
        auto *frame = new MyFrame(wxT("Hello wxWidgets!"));
        frame->Show(true);
        return true;
    }
};

应该很好理解,做最简单的程序,我们只需要对 wxApp 类的 OnInit 虚函数进行重定义(当然你想把函数声明部分写成 “bool OnInit() override” 我也不拦着你,看个人习惯)。OnInit 函数是 wxApp 类的一个重要成员,它在应用程序启动时被调用,用于执行应用程序的初始化操作。

函数体第一句代码:创建了一个名为 frame 的指针,指向 MyFrame 类的实例。MyFrame 类是一个从 wxFrame 派生的自定义类,表示应用程序的主窗口。这里将窗口标题设置为 “Hello wxWidgets!”。

函数体第二句代码:显示主窗口。其实 Show 的参数写不写都无所谓,它默认参数就是 true

函数体第三句代码:返回 true,表示应用程序初始化成功,如果返回 false,将被认为初始化失败,程序将退出,main 函数体中调用的 wxEntry 函数将返回非0值(我这里返回了255)。

4. MyFrame 主窗口

// 就是剩下的那部分代码。代码有点长,不重新贴出来了,以免觉得我在水文……

MyFrame 继承于 wxFrame 类,它是一个 wxWidgets 的顶级窗口类,通常用于创建主窗口。继承wxFrame 来创建主窗口类的原因是因为 wxFrame 提供了许多方便的方法来管理窗口的生命周期处理窗口事件,以及与操作系统交互。通过继承 wxFrame,我们可以轻松地实现自定义的主窗口类,并利用 wxFrame 提供的方法来处理窗口的生命周期和事件

以上是比较官方的话(当然这不是官方的话),实际情况是——我不继承 wxFrame,我似乎没法创建主窗口,直接继承 wxWindow?好像它默认就没法直接显示到系统UI上,因为它需要有父对象,而父对象……wxFrame 就很不错,它父对象可以设置为空

wxFrame 有一个特点,就是如果它只有一个直属的控件,那么这个控件就会布满整个 wxFrame 的客户区域(客户区域指的就是用户主要操作的区域,排除那些默认边框、默认顶部栏等部分)。在这个程序中,只有一个类型为 wxPanel 的面板 panel 的父对象设置成 thispanel 自然而然就占据了整个客户区域:

auto *panel = new wxPanel(this, wxID_ANY);

接下来,我们又在面板 panel 中添加了一个名为 button 的按钮:

auto *button = new wxButton(panel, wxID_ANY, wxT("Click me!"),
                            wxPoint(60, 40), wxSize(100, 30));

按钮标题为“Click me!”,且位于 panel 的 (60, 40) 位置,大小为 (100, 30)。

创建完按钮,我们又为按钮绑定了一个点击事件,事件ID为 wxEVT_BUTTON

button->Bind(wxEVT_BUTTON, &MyFrame::OnButtonClicked, this);

是不是看不出来它是个点击事件ID?没错,我也看不出来[狗头]。当然还有其他的较为精细化的事件,例如:wxEVT_LEFT_DOWNwxEVT_LEFT_UPwxEVT_MIDDLE_DOWNwxEVT_MIDDLE_UPwxEVT_RIGHT_DOWNwxEVT_RIGHT_UPwxEVT_MOTION 等,这些事件并不是按钮特有的,我们可以继承 wxWindow 并通过实现这些事件来自定义一个按钮,当然这是后话。

接着,我们定义了一个按钮事件触发函数:

void OnButtonClicked(wxCommandEvent &event)
{
    wxUnusedVar(event);
    wxMessageBox(wxT("Hello, wxWidgets!"), wxT("Hello"), wxOK | wxICON_INFORMATION);
}

这个函数的参数是由事件决定的,wxEVT_BUTTON 事件对应的事件对象类型就是 wxCommandEvent。在函数中,我们创建了一个消息对话框,对话框的标题为“Hello”,内容为“Hello, wxWidgets!”。

往下看,类声明中还有一句代码:

wxDECLARE_EVENT_TABLE();

熟悉MFC的小伙伴应该知道它的作用,它用于创建事件表,而事件表的定义就在类声明的下方:

wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_BUTTON(wxID_ANY, MyFrame::OnButtonClicked)
wxEND_EVENT_TABLE()

其实这个事件表有点多此一举,因为在创建按钮时,已经使用了 Bind 函数进行了绑定。这里单纯是为了把事件表的使用方式给展示出来,大家在实际使用时可二选一。具体 wxWidgets 的事件介绍我放在了后面的章节。

三、其他细节问题

  1. 在程序中,我们可以看到凡是输入文本的地方,我们都用了 wxT 宏。这个宏的主要作用就是把文本类型转换为 wxWidgets 能识别和显示的文本类型。就目前 3.2 而言,在Windows下,这个宏加不加都不会有什么影响,而 Linux 下,去掉这个宏,中文就没法显示了,当然你可以使用“宽字符串”来 wxWidgets 正确显示中文,它在 wxUSE_UNICODE 宏未定义的情况下等同于 wxT,例如:L"你好,wxWidgets!"

  2. wxID_ANY 表示由 wxWidgets 自动分配ID,这些自动分配的ID都是负数,也就是说,如果我们要自定义ID,就不要把ID设置成负数,否则很容易与 wxWidgets 自动分配的ID冲突


【wxWidgets 教程】HelloWorld 程序详细介绍(二) 至此完毕,欢迎大家指正!还请大家点点赞,给我点动力~~

上一篇:【wxWidgets 教程】安装、配置、HelloWorld篇(一)
下一篇:【wxWidgets 教程】事件篇Ⅰ(三)文章来源地址https://www.toymoban.com/news/detail-736170.html

到了这里,关于【wxWidgets 教程】HelloWorld 程序详细介绍(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • wxWidgets学习笔记:wxTreeCtrl使用详解

    官网给出的samp 2.6.1获取根节点是否选中 要获取wxTreeCtrl控件的根节点的选择状态,您可以使用wxTreeCtrl控件的GetItemState()方法。以下是一个示例代码,用于获取根节点是否被选中: 复制 在这个例子中,我们使用GetRootItem()方法获取树的根节点的wxTreeItemId。然后,我们使用GetIte

    2024年02月09日
    浏览(28)
  • vs2013 编译wxwidgets界面库

    首先进入官网下载,本人再git上下载的基本都编译失败 https://www.wxwidgets.org/ 在网站里面找最新的就可以,下载之后放在一个目录,找到vs的目录  然后找到wx_vc12.sln,打开编译即可 Debug、Release编译出来的是静态库 DLL Debug、DLL Release编译出来的是动态库

    2024年02月16日
    浏览(24)
  • wxWidgets(1):在Ubuntu 环境中搭建wxWidgets 库环境,安装库和CodeBlocks的IDE,可以运行demo界面了,继续学习中

    选择这个主要是因为完全的开源,不想折腾 Qt的库,而且打包的文件比较大。 网络上面有很多的对比,而且使用QT的人比较多。 但是我觉得wxwidgets 更加偏向 c++ 语法本身,也有助学习C++。 没有太多的特殊封装,而且商业化更加友好,打包软件也比较少。 更偏向原生的系统,

    2024年02月07日
    浏览(39)
  • wxWidgets实战:使用mpWindow绘制阻抗曲线

    选择模型时,需要查看model的谐振频率,因此需要根据s2p文件绘制一张阻抗曲线。 如下图所示: 左侧使用mpWindow,右侧使用什么? https://forums.wxwidgets.org/viewtopic.php?t=44928 https://iwbnwif.github.io/freechart_docs/html/index.html

    2024年01月15日
    浏览(30)
  • wxWidgets学习笔记:列表框wxListBox使用详解

    这个wxListBox控件的构造函数有以下参数: m_PanelFootprintFilter:wxPanel类型的父窗口,表示将wxListBox添加到该窗口中。 wxID_ANY:wxWidgets自动生成的唯一标识符,用于在事件处理程序中引用该控件。 wxDefaultPosition:wxPoint类型的控件初始位置,表示该控件在父窗口中的初始位置。 w

    2024年02月13日
    浏览(28)
  • wxWidgets学习笔记:Tab页wxNotebook使用详解

    在该pannel上面的创建控件 其中bUpperSizer

    2024年02月16日
    浏览(29)
  • wxwidgets Ribbon构建多个page与按钮响应

    新建一个控制台应用程序,添加好头文件的依赖与lib库文件的依赖,修改属性:  将进入ribbon界面的文件与主界面的类分开: 1、RibbonSample.cpp #include \\\"stdafx.h\\\" #include \\\"MyFrame.h\\\" class MyApp : public wxApp { public:     bool OnInit() wxOVERRIDE; }; wxDECLARE_APP(MyApp); wxIMPLEMENT_APP(MyApp); bool MyApp::O

    2024年02月14日
    浏览(23)
  • 【前车之鉴】: 2023最新教程-将java程序打包到maven私服的正确打开方式,详细流程介绍不怕你掌握不了

    一是当前网络上一些博客有遗漏部分,这里做补充,二是网上思路没错,但是有些关键配置maven官方做了变更,其三:更详细,更面向初次使用的developer 上图所示的步骤基本就是本文的框架,其实打包逻辑比较清晰,仅仅是过程复杂,但有过公司开发经历的同学应该能get到这

    2024年02月11日
    浏览(32)
  • 【Element UI详细介绍】

    Element UI 是一个基于 Vue 2.0 的桌面端组件库,主要用于构建快速、简洁的用户界面,Element UI 提供一套丰富的组件和工具,能够帮助开发者快速构建高质量的 Vue 应用,它由饿了么前端团队开发,并且开放源代码。 官网链接: 官网 另外一个与ElmentUI类似提供基于Vue2.0的组件库是

    2024年01月25日
    浏览(28)
  • gin介绍及helloworld

    Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的 net/http 足够简单,性能也非常不错 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团

    2024年01月21日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包