将程序界面和业务代码分离对提高开发效率和代码可读性是很有帮助的,主流的UI库如qt、wxWidgets和gtk都拥有自己的实现方法,下面分别演示一下。
1.1 编写XRC文件
wxWidgets支持通过xml格式定义UI界面并保存为XRC文件。通过XRC文件可以实现界面代码分离,但缺点是发布的程序相比非XRC版本体积会增加一些。
下面是官方案例中的XRC文件示例,实现了一个对话框,将其保存为resource.xrc。
<?xml version="1.0" ?>
<resource version="2.3.0.1">
<object class="wxDialog" name="SimpleDialog">
<title>Simple dialog</title>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxTextCtrl" name="text"/>
<option>1</option>
<flag>wxALL|wxEXPAND</flag>
<border>10</border>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<object class="sizeritem">
<object class="wxButton" name="clickme_btn">
<label>Click</label>
</object>
<flag>wxRIGHT</flag>
<border>10</border>
</object>
<object class="sizeritem">
<object class="wxButton" name="wxID_OK">
<label>OK</label>
</object>
<flag>wxLEFT</flag>
<border>10</border>
</object>
<orient>wxHORIZONTAL</orient>
</object>
<flag>wxALL|wxALIGN_CENTRE</flag>
<border>10</border>
</object>
</object>
</object>
</resource>
wxWidgets诞生时间比较早,XRC相关的RAD工具有很多,可以参考官方百科,选择自己喜欢的工具进行辅助开发。
1.2 编写工程文件
编写main.cpp文件如下所示,通过主窗口调用这个对话框。初始化XRC界面之后,通过宏XRCCTRL调用其中的窗口和控件类并连接事件处理和回调函数。
// --- main.cpp ---
#include <wx/wx.h>
#include <wx/xrc/xmlres.h>
extern void InitXmlResource();
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString &title);
void OnClickme(wxCommandEvent &event);
void OnShowDialog(wxCommandEvent &event);
};
class MyApp : public wxApp
{
public:
bool OnInit() override;
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
wxXmlResource::Get()->InitAllHandlers();
InitXmlResource();
MyFrame *frame = new MyFrame("Main Window");
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString &title)
: wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxSize(400, 300))
{
// Create a panel to put the button on
wxPanel *panel = new wxPanel(this);
// Create a button to show the dialog
wxButton *showDialogBtn = new wxButton(panel, wxID_ANY, "Show Dialog", wxPoint(150, 120));
showDialogBtn->Bind(wxEVT_BUTTON, &MyFrame::OnShowDialog, this);
}
void MyFrame::OnShowDialog(wxCommandEvent &event)
{
// Create and show the dialog if not already created
wxDialog m_dialog;
if (!wxXmlResource::Get()->LoadDialog(&m_dialog, this, "SimpleDialog"))
{
wxMessageBox("Failed to load dialog");
return;
}
wxTextCtrl *pText = XRCCTRL(m_dialog, "text", wxTextCtrl);
if (pText)
pText->ChangeValue("This is a simple dialog");
XRCCTRL(m_dialog, "clickme_btn", wxButton)->Bind(wxEVT_BUTTON, &MyFrame::OnClickme, this);
m_dialog.ShowModal();
}
void MyFrame::OnClickme(wxCommandEvent &event)
{
wxMessageBox("clickme_btn is clicked");
}
按照官方文档编写CMakeLists.txt文件如下,通过cmake调用wxrc将resource.xrc编译为cpp文件,再内嵌入发布的可执行文件中,这样最终发布的程序就不需要带着.xrc文件,当然cpp源码也得做相应的适配才行。这里通过vcpkg工具链编译,相关参数通过vcpkg.cmake传入。