找回密码
 立即注册
首页 业界区 业界 在Linux下使用wxWidgets进行跨平台GUI开发(三) ...

在Linux下使用wxWidgets进行跨平台GUI开发(三)

翁谌缜 2025-9-25 10:51:25
创建wxWidgets应用程序

在本文中,我们将了解创建wxWidgets应用程序所需的基础知识。首先创建一个简单的示例程序,展示如何显示图标;接着通过另一个示例演示事件的使用方法;最后探讨wxWidgets应用程序中控件之间的通信机制。
一个简单的应用程序

首先我们创建一个非常基础的wxWidgets程序。
  1. // simple.h
  2. #include <wx/wx.h>
  3. class Simple : public wxFrame
  4. {
  5. public:
  6.     Simple(const wxString& title);
  7. };
  8. // simple.cpp
  9. #include "simple.h"
  10. Simple::Simple(const wxString& title)
  11.        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
  12. {
  13.   Centre();
  14. }
  15. // main.h
  16. #include <wx/wx.h>
  17. class MyApp : public wxApp
  18. {
  19.   public:
  20.     virtual bool OnInit();
  21. };
  22. // main.cpp
  23. #include "main.h"
  24. #include "simple.h"
  25. IMPLEMENT_APP(MyApp)
  26. bool MyApp::OnInit()
  27. {
  28.     Simple *simple = new Simple(wxT("Simple"));
  29.     simple->Show(true);
  30.     return true;
  31. }
复制代码
用CMake构建工具,须编写CMakeLists.txt
  1. cmake_minimum_required(VERSION 3.10)
  2. project(simple)
  3. if(WIN32)
  4.   find_package(wxWidgets 3.2 REQUIRED COMPONENTS core base CONFIG)
  5. else()
  6.   find_package(wxWidgets 3.2 REQUIRED COMPONENTS core base)
  7. endif()
  8. if(wxWidgets_USE_FILE)                 # not defined in CONFIG mode
  9.   include(${wxWidgets_USE_FILE})
  10. endif()
  11. set(SRC_FILES
  12.     main.cpp
  13.     simple.cpp
  14.     )
  15. # Define the build target for the executable, e.g. windows application.
  16. add_executable(${PROJECT_NAME} WIN32 MACOSX_BUNDLE ${SRC_FILES})
  17. target_link_libraries(${PROJECT_NAME} ${wxWidgets_LIBRARIES})
  18. if(MSVC)
  19.   target_include_directories(${PROJECT_NAME} PUBLIC "${wxWidgets_INCLUDE_DIRS}/msvc")
  20. endif()
  21. if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  22.   message(STATUS "Configuring for 64-bit build.")
  23.   set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/out)
  24.   if(NOT MSVC)
  25.     set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE})
  26.   endif()
  27. else()
  28.   message(STATUS "Configuring for 32-bit build.")
  29.   set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/out/b32)
  30.   if(NOT MSVC)
  31.     set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/out/b32/${CMAKE_BUILD_TYPE})
  32.   endif()
  33. endif()
复制代码
现在,生成的可执行程序将会放在out文件夹内部。值得一提的是CMake采用Config模式在Windows下构建wxWidgets应用程序更好用,而在Linux下这个模式反而更麻烦了。
这个非常基础的示例在屏幕上显示了一个小窗口。该窗口位于屏幕中央。
Centre();                //这个方法将窗口在屏幕上水平和垂直居中。
IMPLEMENT_APP(MyApp)         //实现应用程序的代码被隐藏在这个宏后面。
这段代码通常是复制粘贴复用的,我们一般不需要关心它。
运行效果例如在Linux下将显示
1.png

应用程序图标

在本示例中,我们为应用程序提供了一个图标。在窗口左上角显示小图标已成为标准做法,该图标是程序的图形标识。
  1. // icon.h
  2. #include <wx/wx.h>
  3. class Icon : public wxFrame
  4. {
  5. public:
  6.     Icon(const wxString& title);
  7. };
  8. // icon.cpp
  9. #include "icon.h"
  10. Icon::Icon(const wxString& title)
  11.        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
  12. {
  13.   SetIcon(wxIcon(wxT("web.xpm")));
  14.   Centre();
  15. }
  16. // main.h
  17. #include <wx/wx.h>
  18. class MyApp : public wxApp
  19. {
  20.   public:
  21.     virtual bool OnInit();
  22. };
  23. // main.cpp
  24. #include "main.h"
  25. #include "icon.h"
  26. IMPLEMENT_APP(MyApp)
  27. bool MyApp::OnInit()
  28. {
  29.     Icon *icon = new Icon(wxT("Icon"));
  30.     icon->Show(true);
  31.     return true;
  32. }
复制代码
在我们的示例中,我们展示了一个小小的网页图标。
SetIcon(wxIcon(wxT("web.xpm")));
只需一行代码即可显示应用程序图标。XPM(X PixMap)是一种ASCII图像格式。
一个简单的按钮

在以下示例中,我们将在框架部件上创建一个按钮。我们将展示如何创建一个简单的事件处理器。
  1. // button.h
  2. #include <wx/wx.h>
  3. class Button : public wxFrame
  4. {
  5. public:
  6.     Button(const wxString& title);
  7.     void OnQuit(wxCommandEvent & event);
  8. };
  9. // button.cpp
  10. #include "button.h"
  11. Button::Button(const wxString& title)
  12.        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 150))
  13. {
  14.   wxPanel *panel = new wxPanel(this, wxID_ANY);
  15.   wxButton *button = new wxButton(panel, wxID_EXIT, wxT("Quit"),
  16.       wxPoint(20, 20));
  17.   Connect(wxID_EXIT, wxEVT_COMMAND_BUTTON_CLICKED,
  18.       wxCommandEventHandler(Button::OnQuit));
  19.   button->SetFocus();
  20.   Centre();
  21. }
  22. void Button::OnQuit(wxCommandEvent & WXUNUSED(event))
  23. {
  24.     Close(true);
  25. }
  26. // main.h
  27. #include <wx/wx.h>
  28. class MyApp : public wxApp
  29. {
  30.   public:
  31.     virtual bool OnInit();
  32. };
  33. // main.cpp
  34. #include "main.h"
  35. #include "button.h"
  36. IMPLEMENT_APP(MyApp)
  37. bool MyApp::OnInit()
  38. {
  39.     Button *btnapp = new Button(wxT("Button"));
  40.     btnapp->Show(true);
  41.     return true;
  42. }
复制代码
首先我们创建一个 wxPanel 部件,它将被放置在 wxFrame 部件内部。
我们创建一个 wxButton 部件,将其放置在面板上。我们为按钮使用了预定义的 wxID_EXIT ID,这会使按钮上显示一个小的退出图标。按钮的标签是"退出"(Quit)。按钮被手动定位在坐标 x=20,y=20 处。坐标系的起点位于左上角。
当我们点击按钮时,会生成一个 wxEVT_COMMAND_BUTTON_CLICKED 事件。我们将该事件连接到 Button 类的 OnQuit 方法。因此当我们点击按钮时,就会调用 OnQuit 方法。
我们将键盘焦点设置在该按钮上。这样当我们按下回车键时,就会触发按钮的点击事件。
在 OnQuit 方法内部,我们调用了 Close 方法。这将终止我们的应用程序。
(补充说明:在 wxWidgets 框架中,调用 Close() 方法会触发 wxEVT_CLOSE_WINDOW 事件,该事件的默认处理程序会调用 wxWindow:estroy() 来销毁窗口。对于应用程序的主窗口来说,这会进一步导致整个应用程序退出,前提是没有其他顶级窗口存在。这是 wxWidgets 应用程序的标准退出流程之一)
组件通信

了解组件如何在应用程序中进行通信非常重要。请看以下示例。
  1. // Panels.h
  2. #include <wx/wx.h>
  3. #include <wx/panel.h>
  4. class LeftPanel : public wxPanel
  5. {
  6. public:
  7.     LeftPanel(wxPanel *parent);
  8.     void OnPlus(wxCommandEvent & event);
  9.     void OnMinus(wxCommandEvent & event);
  10.     wxButton *m_plus;
  11.     wxButton *m_minus;
  12.     wxPanel *m_parent;
  13.     int count;
  14. };
  15. class RightPanel : public wxPanel
  16. {
  17. public:
  18.     RightPanel(wxPanel *parent);
  19.     void OnSetText(wxCommandEvent & event);
  20.     wxStaticText *m_text;
  21. };
  22. const int ID_PLUS = 101;
  23. const int ID_MINUS = 102;
  24. // Panels.cpp
  25. #include <wx/stattext.h>
  26. #include "Communicate.h"
  27. LeftPanel::LeftPanel(wxPanel * parent)
  28.        : wxPanel(parent, -1, wxPoint(-1, -1), wxSize(-1, -1), wxBORDER_SUNKEN)
  29. {
  30.   count = 0;
  31.   m_parent = parent;
  32.   m_plus = new wxButton(this, ID_PLUS, wxT("+"),
  33.       wxPoint(10, 10));
  34.   m_minus = new wxButton(this, ID_MINUS, wxT("-"),
  35.       wxPoint(10, 60));
  36.   Connect(ID_PLUS, wxEVT_COMMAND_BUTTON_CLICKED,
  37.       wxCommandEventHandler(LeftPanel::OnPlus));
  38.   Connect(ID_MINUS, wxEVT_COMMAND_BUTTON_CLICKED,
  39.       wxCommandEventHandler(LeftPanel::OnMinus));
  40. }
  41. void LeftPanel::OnPlus(wxCommandEvent & WXUNUSED(event))
  42. {
  43.   count++;
  44.   Communicate *comm = (Communicate *) m_parent->GetParent();
  45.   comm->m_rp->m_text->SetLabel(wxString::Format(wxT("%d"), count));
  46. }
  47. void LeftPanel::OnMinus(wxCommandEvent & WXUNUSED(event))
  48. {
  49.   count--;
  50.   Communicate *comm = (Communicate *) m_parent->GetParent();
  51.   comm->m_rp->m_text->SetLabel(wxString::Format(wxT("%d"), count));
  52. }
  53. RightPanel::RightPanel(wxPanel * parent)
  54.        : wxPanel(parent, wxID_ANY, wxDefaultPosition,
  55.          wxSize(270, 150), wxBORDER_SUNKEN)
  56. {
  57.     m_text = new wxStaticText(this, -1, wxT("0"), wxPoint(40, 60));
  58. }
  59. // Communicate.h
  60. #include "Panels.h"
  61. #include <wx/wxprec.h>
  62. class Communicate : public wxFrame
  63. {
  64. public:
  65.     Communicate(const wxString& title);
  66.     LeftPanel *m_lp;
  67.     RightPanel *m_rp;
  68.     wxPanel *m_parent;
  69. };
  70. // Communicate.cpp
  71. #include "Communicate.h"
  72. Communicate::Communicate(const wxString& title)
  73.        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(290, 150))
  74. {
  75.   m_parent = new wxPanel(this, wxID_ANY);
  76.   wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
  77.   m_lp = new LeftPanel(m_parent);
  78.   m_rp = new RightPanel(m_parent);
  79.   hbox->Add(m_lp, 1, wxEXPAND | wxALL, 5);
  80.   hbox->Add(m_rp, 1, wxEXPAND | wxALL, 5);
  81.   m_parent->SetSizer(hbox);
  82.   this->Centre();
  83. }
  84. // main.h
  85. #include <wx/wx.h>
  86. class MyApp : public wxApp
  87. {
  88.   public:
  89.     virtual bool OnInit();
  90. };
  91. // main.cpp
  92. #include "main.h"
  93. #include "Communicate.h"
  94. IMPLEMENT_APP(MyApp)
  95. bool MyApp::OnInit()
  96. {
  97.     Communicate *communicate = new Communicate(wxT("Widgets communicate"));
  98.     communicate->Show(true);
  99.     return true;
  100. }
复制代码
在我们的示例中,我们有两个面板:左侧面板和右侧面板。左侧面板有两个按钮,右侧面板有一个静态文本控件。这些按钮可以改变静态文本中显示的数字。现在的问题是:我们如何获取指向该静态文本控件的指针?
我们保存了指向 LeftPanel 父部件的指针,该父部件是一个 wxPanel 组件。
Communicate *comm = (Communicate *) m_parent->GetParent();
comm->m_rp->m_text->SetLabel(wxString::Format(wxT("%d"), count));
这两行代码是本示例中最关键的部分,它们展示了如何访问位于另一个面板上的静态文本控件。首先我们获取左右两个面板的父部件,这个父部件持有指向右侧面板的指针,而右侧面板又保存着指向静态文本控件的指针。在wxWidgets框架中,这种通过父窗口访问同级控件的模式是跨面板通信的典型实现方式。
至此,在wxWidgets教程的这一部分中,我们已经创建了一些简单的程序。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册