【wxWidgets 教程】安装、配置、HelloWorld篇(一)

一、下载 wxWidgets 源码

下载地址:https://github.com/wxWidgets/wxWidgets.git
这里,我下载了wxWidgets 3.2.2.1,接下来便以这个版本为示例进行详细的安装介绍。

二、编译配置

在进行源码编译前,要确保已经安装了CMake。CMake的下载路径:https://cmake.org/download/
下面是一段简单的构建wxWidgets库的CMake脚本:

include(FetchContent)
FetchContent_Declare(
  wxWidgets
  GIT_REPOSITORY "https://github.com/wxWidgets/wxWidgets.git"
  GIT_TAG v3.2.2.1
)
FetchContent_MakeAvailable(wxWidgets)

它会从GitHub上把wxWidgets源码下载下来。执行CMake脚本,等待一段时间,可看到有以下输出:

-- Which libraries should wxWidgets use?
    wxUSE_STL:      OFF      (use C++ STL classes)
    wxUSE_REGEX:    builtin  (enable support for wxRegEx class)
    wxUSE_ZLIB:     builtin  (use zlib for LZW compression)
    wxUSE_EXPAT:    builtin  (use expat for XML parsing)
    wxUSE_LIBJPEG:  builtin  (use libjpeg (JPEG file format))
    wxUSE_LIBPNG:   builtin  (use libpng (PNG image format))
    wxUSE_LIBTIFF:  builtin  (use libtiff (TIFF file format))
    wxUSE_NANOSVG:  builtin  (use NanoSVG for rasterizing SVG)
    wxUSE_LIBLZMA:  OFF      (use liblzma for LZMA compression)

-- Configured wxWidgets 3.2.2 for Windows-10.0.22000
    Min OS Version required at runtime:                Windows Vista / Windows Server 2008 (x64 Edition)
    Which GUI toolkit should wxWidgets use?            msw  
    Should wxWidgets be compiled into single library?  OFF
    Should wxWidgets be linked as a shared library?    ON
    Should wxWidgets support Unicode?                  ON
    What wxWidgets compatibility level should be used? 3.0

这里专门对两个为 “OFF” 的选项进行解析:

  1. wxUSE_STL 是一个在wxWidgets库的C++代码中用于启用或禁用标准模板库 (STL) 的宏定义。它控制库中使用STL的部分,例如使用 std::string 替代 wxString。当 wxUSE_STL 被定义为 “ON” 时,表示启用STL支持,而当它被定义为0时,则表示禁用STL支持。设置 wxUSE_STL 的值将会影响wxWidgets库的构建和使用方式。启用STL支持将允许开发人员更容易地使用C++标准库中的一些数据结构和算法,从而简化代码的编写过程。禁用STL支持可以减少库的大小,并提高代码的性能,因为STL的实现可能会导致一些额外的开销。
  2. wxUSE_LIBLZMA 用于启用或禁用wxWidgets对liblzma库的支持。liblzma是一个用于数据压缩和解压缩的库,支持多种压缩格式,包括XZ和LZMA。当需要使用wxWidgets中与liblzma相关的功能时,例如通过 wxArchiveClass 类解压缩XZ格式的归档文件,需要确保 wxUSE_LIBLZMA 设置为 “ON”,并确保已安装liblzma库及其头文件。

其他选项默认都是builtin,即已内建到了wxWidgets中,我们可以不用管。

继续往下看,我们可以看到这段输出:

Which GUI toolkit should wxWidgets use?            msw  

这说明我目前所用的是 wxMSW 端口,它会自动识别我们的系统并作出选择。当然,如果我们想自己设置其他平台端口,可以设置CMake脚本的 wxBUILD_TOOLKIT 变量值,如果要知道当前系统上wxWidgets可用的GUI工具集,可查看 wxTOOLKIT_OPTIONS 的变量值,另外,wxPLATFORM 变量记录了当前的操作系统平台是什么。我这里wxPLATFORM的值为WIN32

还有这句输出:

Should wxWidgets be compiled into single library?  OFF

默认情况下,wxWidgets编译输出的是多个库文件,如果想编译成一个库文件,可更改选项 wxBUILD_MONOLITHIC 为 “ON”,然后重新构建CMake项目。

接下来,我们写一个最简单的wxWidgets项目。先写好CMake脚本。

cmake_minimum_required(VERSION 3.24)
project(wxWidget_test1)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY bin)

include(cmake/Find_wxWidget.cmake)
add_executable(wxWidget_test1 main.cpp)
target_link_libraries(wxWidget_test1 PRIVATE
                      # wxmono
                      wx::net wx::core wx::base)

# Windows下,在构建完成后,将依赖的动态链接库文件拷贝到可执行文件输出目录下
add_custom_command(TARGET wxWidget_test1
                   POST_BUILD COMMAND "${CMAKE_COMMAND}" -E
                   copy_if_different "$<TARGET_RUNTIME_DLLS:wxWidget_test1>" "$<TARGET_FILE_DIR:wxWidget_test1>"
                   VERBATIM COMMAND_EXPAND_LISTS)

# Windows下,需添加以下属性,否则编译时会出现main函数未定义的错误
set_target_properties(wxWidget_test1 PROPERTIES WIN32_EXECUTABLE ON)

上述脚本中,我把构建wxWidgets库的脚本指令放到了项目根目录的“cmake”目录的 Find_wxWidget.cmake 中(即本文开头的第一段CMake脚本)。
这个项目使用wxWidgets的 wx::net wx::core wx::base 三个模块,当然这是把wxWidgets编译成多个库文件的情况下的使用方法。
如果编译成一个库文件(即 wxBUILD_MONOLITHIC 为 ON)则应该在 target_link_libraries 中添加 wxmono(脚本中我把这行给注释了),且不能独立包含模块,此时的 target_link_libraries 应该写成:

target_link_libraries(wxWidget_test1 PRIVATE wxmono)

三、代码编写

#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. 首先,我们需要包含wxWidgets的头文件。
  2. 接下来,我们需要创建一个 wxFrame 派生类来实现我们的主窗口。在 MyFrame 类中,我们需要创建主窗口的各种控件和布局,并处理它们的事件。
  3. 我们需要创建一个wxWidgets应用程序类,该类派生自 wxApp 类。在此类中,我们需要实现 OnInit() 函数,该函数将在应用程序启动时被调用。在 OnInit() 函数中,我们需要创建我们的主窗口。
  4. 最后,使用 wxIMPLEMENT_APP 宏指定我们的应用程序类。

编译后运行结果如下:
程序运行结果

至此,一个最基本的wxWidgets库的安装配置和使用方法介绍结束。

四、CMake说明

  • CMake构建指令
    cmake .
    

    cmake 后面接的要是根 CMakeLists.txt 文件的路径,执行后将会把当前目录作为构建目录. 意味着根源码目录作为构建目录。

  • CMake编译指令
    cmake --build .
    

    注意,此时的 . 指的是构建目录所在路径,要与CMake构建时的指令区分开来。


版权声明:本文为Xiao_Ley原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>