通过重载c++operator,实现一种轻松的wxWidgets界面编程风格,如html编写页面一样直观容易。

举一例,一个界面页有四块区,如果是开发html的话,是从头到脚一气书写

<div id='0'>
<div id='1'>
<input type="button" onclick="handler()">
</div>
<div id='2'>
<input type="button" onclick="handler()">
</div>
<div id='3'>
<input type="button" onclick="handler()">
</div>
<div id='4'>
<input type="button" onclick="handler()">
</div>
</div>

我的目标是,让c++开发的代码书写也一气呵成

Frame* frame = new Frame;
layout::begin(new layout)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::begin(new layout)
(new button) [ onclick = [] (event&) {} ]
(layout::end)
)
(layout::end, [=] (layout& layout) {
frame->SetLayout(layout);
});

菜单布局编写直观自然,处理器函数绑定同时到位

Frame* frame = new Frame;
menu::begin(new MenuBar)
("File",
menu::begin(new Menu)
            (ID_OPEN, "open", [=] (event&) { })
(ID_NEW, "new", [=] (event&) { })
(menu::end)
)
("About",
menu::begin(new Menu)
             (ID_HELP, "help", [=] (event&) { })
(menu::end)
)
(menu::end, [=] (MenuBar* mb) {
frame->SetMenuBar(mb);
});

理想总是美好的,现在回到现实中的界面开发,让人眼痛的c++代码,

1 必须在多处代码操作,步骤烦多,分散在多处代码。

2 布局编写不符合人的思维-将整体拆分再拆分,而是从枝节末端创建一层一层往上添加挂钩。

MFC,WTL与wxWidgets的开发步骤类似,这里只关注wxWidgets,

1 在头文件中,自定义窗口类声明事件(窗口消息)分派函数;

2 在源文件中,添加事件(窗口消息)分派函数的实现宏;

3 添加一个事件(窗口消息)处理器函数,

3-1 在头文件中,声明为自定义窗口类的成员函数

3-2 在源文件中,实现该函数

3-3 在源文件中,在那个TABLE宏里添加事件id,处理器函数

4 在某个窗口容器的初始化回调中,创建事件id对应的子窗口/控件,设置相关的id

5 过了一段时间后,维护某个控件的处理器函数

5-1 在布局代码中找到这个控件,看到它相关的id

5-2 在源代码找到分派事件的窗口类,在它的TABLE宏里众多条目中找出对应项

5-3 最后才定位到目标处理器函数

做一样事情,却要在多处代码文件中跳转切换,只要漏了一步又会浪费时间调试一翻,实在烦人烦心。

// MyFrame.h

enum
{
ID_SOME
}; class MyFrame : public wxFrame
{
public:
void hanlde_some_event(wxEvent&);
private:
wxDECLARE_EVENT_TABLE()
}
// MyFrame.cpp

wxBEGIN_EVENT_TABLE(MyFrame,  wxFrame)
EVT_XXXX(ID_SOME, &MyFrame::handle_some_event)
wxEND_EVENT_TABLE() void MyFrame::handle_some_event(wxEvent&)
{
// todo
} MyFrame::MyFrame()
{
// ....
this->Add(new wxSomeWindow(this, ID_SOME, ...);
// ....
}

下面是用zwx_helper重写官方layout sample布局的代码的对比

先是官方代码

layout.h https://github.com/wxWidgets/wxWidgets/blob/master/samples/layout/layout.h

layout.cpp https://github.com/wxWidgets/wxWidgets/blob/master/samples/layout/layout.cpp

// ----------------------------------------------------------------------------
// MyFrame
// ---------------------------------------------------------------------------- wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(LAYOUT_ABOUT, MyFrame::OnAbout)
EVT_MENU(LAYOUT_QUIT, MyFrame::OnQuit) EVT_MENU(LAYOUT_TEST_PROPORTIONS, MyFrame::TestProportions)
EVT_MENU(LAYOUT_TEST_SIZER, MyFrame::TestFlexSizers)
EVT_MENU(LAYOUT_TEST_NB_SIZER, MyFrame::TestNotebookSizers)
EVT_MENU(LAYOUT_TEST_GB_SIZER, MyFrame::TestGridBagSizer)
EVT_MENU(LAYOUT_TEST_SET_MINIMAL, MyFrame::TestSetMinimal)
EVT_MENU(LAYOUT_TEST_NESTED, MyFrame::TestNested)
EVT_MENU(LAYOUT_TEST_WRAP, MyFrame::TestWrap)
wxEND_EVENT_TABLE() // Define my frame constructor
MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, "wxWidgets Layout Demo")
{
SetIcon(wxICON(sample)); // Make a menubar
wxMenu *file_menu = new wxMenu; file_menu->Append(LAYOUT_TEST_PROPORTIONS, "&Proportions demo...\tF1");
file_menu->Append(LAYOUT_TEST_SIZER, "Test wx&FlexSizer...\tF2");
file_menu->Append(LAYOUT_TEST_NB_SIZER, "Test &notebook sizers...\tF3");
file_menu->Append(LAYOUT_TEST_GB_SIZER, "Test &gridbag sizer...\tF4");
file_menu->Append(LAYOUT_TEST_SET_MINIMAL, "Test Set&ItemMinSize...\tF5");
file_menu->Append(LAYOUT_TEST_NESTED, "Test nested sizer in a wxPanel...\tF6");
file_menu->Append(LAYOUT_TEST_WRAP, "Test wrap sizers...\tF7"); file_menu->AppendSeparator();
file_menu->Append(LAYOUT_QUIT, "E&xit", "Quit program"); wxMenu *help_menu = new wxMenu;
help_menu->Append(LAYOUT_ABOUT, "&About", "About layout demo..."); wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File");
menu_bar->Append(help_menu, "&Help"); // Associate the menu bar with the frame
SetMenuBar(menu_bar); #if wxUSE_STATUSBAR
CreateStatusBar();
SetStatusText("wxWidgets layout demo");
#endif // wxUSE_STATUSBAR wxPanel* p = new wxPanel(this, wxID_ANY); // we want to get a dialog that is stretchable because it
// has a text ctrl in the middle. at the bottom, we have
// two buttons which. wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); // 1) top: create wxStaticText with minimum size equal to its default size
topsizer->Add(
new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_RIGHT)." ),
wxSizerFlags().Align(wxALIGN_RIGHT).Border(wxALL & ~wxBOTTOM, ));
topsizer->Add(
new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_LEFT)." ),
wxSizerFlags().Align(wxALIGN_LEFT).Border(wxALL & ~wxBOTTOM, ));
topsizer->Add(
new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_CENTRE_HORIZONTAL)." ),
wxSizerFlags().Align(wxALIGN_CENTRE_HORIZONTAL).Border(wxALL & ~wxBOTTOM, )); // 2) top: create wxTextCtrl with minimum size (100x60)
topsizer->Add(
new wxTextCtrl( p, wxID_ANY, "My text (wxEXPAND).", wxDefaultPosition, wxSize(,), wxTE_MULTILINE),
wxSizerFlags().Expand().Border(wxALL, )); // 2.5) Gratuitous test of wxStaticBoxSizers
wxBoxSizer *statsizer = new wxStaticBoxSizer(
new wxStaticBox(p, wxID_ANY, "A wxStaticBoxSizer"), wxVERTICAL );
statsizer->Add(
new wxStaticText(p, wxID_ANY, "And some TEXT inside it"),
wxSizerFlags().Border(wxALL, ));
topsizer->Add(
statsizer,
wxSizerFlags().Expand().Border(wxALL, )); // 2.7) And a test of wxGridSizer
wxGridSizer *gridsizer = new wxGridSizer(, , );
gridsizer->Add(new wxStaticText(p, wxID_ANY, "Label"),
wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL));
gridsizer->Add(new wxTextCtrl(p, wxID_ANY, "Grid sizer demo"),
wxSizerFlags().Align(wxGROW | wxALIGN_CENTER_VERTICAL));
gridsizer->Add(new wxStaticText(p, wxID_ANY, "Another label"),
wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL));
gridsizer->Add(new wxTextCtrl(p, wxID_ANY, "More text"),
wxSizerFlags().Align(wxGROW | wxALIGN_CENTER_VERTICAL));
gridsizer->Add(new wxStaticText(p, wxID_ANY, "Final label"),
wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL));
gridsizer->Add(new wxTextCtrl(p, wxID_ANY, "And yet more text"),
wxSizerFlags().Align(wxGROW | wxALIGN_CENTER_VERTICAL));
topsizer->Add(
gridsizer,
wxSizerFlags().Proportion().Expand().Border(wxALL, )); #if wxUSE_STATLINE
// 3) middle: create wxStaticLine with minimum size (3x3)
topsizer->Add(
new wxStaticLine( p, wxID_ANY, wxDefaultPosition, wxSize(,), wxHORIZONTAL),
wxSizerFlags().Expand());
#endif // wxUSE_STATLINE // 4) bottom: create two centred wxButtons
wxBoxSizer *button_box = new wxBoxSizer( wxHORIZONTAL );
button_box->Add(
new wxButton( p, wxID_ANY, "Two buttons in a box" ),
wxSizerFlags().Border(wxALL, ));
button_box->Add(
new wxButton( p, wxID_ANY, "(wxCENTER)" ),
wxSizerFlags().Border(wxALL, )); topsizer->Add(button_box, wxSizerFlags().Center()); p->SetSizer( topsizer ); // don't allow frame to get smaller than what the sizers tell it and also set
// the initial size as calculated by the sizers
topsizer->SetSizeHints( this );
}

最后是我的代码

std::shared_ptr<MyFrameDelegate> sptr_delegate;

bool MyApp::OnInit()
{
if (!wxApp::OnInit())
return false; MyFrame* frame = new MyFrame;
sptr_delegate = std::shared_ptr<MyFrameDelegate>(new MyFrameDelegate(frame));
MyFrameDelegate* delegate = sptr_delegate.get();
wxPanel* p = new wxPanel((wxWindow*)frame, wxID_ANY);
wxMenuBar* mb =
menu::begin(new wxMenuBar)
("&File",
menu::begin(new wxMenu)
(LAYOUT_TEST_PROPORTIONS, "&Proportions demo...\tF1", &MyFrame::TestMenuCommand, frame)
(LAYOUT_TEST_SIZER, "Test wx&FlexSizer...\tF2", &MyFrame::TestMenuCommand, frame)
(LAYOUT_TEST_NB_SIZER, "Test &notebook sizers...\tF3", &MyFrame::TestMenuCommand, frame)
(LAYOUT_TEST_GB_SIZER, "Test &gridbag sizer...\tF4", frame, [=](wxCommandEvent& event) { frame->TestMenuCommand(event); })
(LAYOUT_TEST_SET_MINIMAL, "Test Set&ItemMinSize...\tF5")
(LAYOUT_TEST_NESTED, "Test nested sizer in a wxPanel...\tF6", frame, [=](wxCommandEvent& event) { sptr_delegate->TestMenuCommand(event); })(LAYOUT_TEST_WRAP, "Test wrap sizers...\tF7")
(menu::end))
("&Help",
menu::begin(new wxMenu)
(LAYOUT_ABOUT, "&About", "About layout demo...")
(menu::end))
("level-tree",
menu::begin(new wxMenu)
(wxID_ANY, "level-1.1",
menu::begin(new wxMenu)
(wxID_ANY, "level-1.1-level-2.1")
(wxID_ANY, "level-1.1-level-2.2")
(menu::end))
(wxID_ANY, "level-1.2",
menu::begin(new wxMenu)
(wxID_ANY, "level-1.2-level-2.1")
(wxID_ANY, "level-1.2-level-2.2")
(menu::end))
(menu::end))
(menu::end,
[=](wxMenuBar* mb) {
frame->SetMenuBar(mb);
}); layout::begin(new wxBoxSizer(wxVERTICAL))
// 1) top: create wxStaticText with minimum size equal to its default size
(new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_RIGHT)." ),
wxSizerFlags().Align(wxALIGN_RIGHT).Border(wxALL & ~wxBOTTOM, ))
(new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_LEFT)." ),
wxSizerFlags().Align(wxALIGN_LEFT).Border(wxALL & ~wxBOTTOM, ))
(new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_CENTRE_HORIZONTAL)." ),
wxSizerFlags().Align(wxALIGN_CENTRE_HORIZONTAL).Border(wxALL & ~wxBOTTOM, )) // 2) top: create wxTextCtrl with minimum size (100x60)
(new wxTextCtrl( p, wxID_ANY, "My text (wxEXPAND).", wxDefaultPosition, wxSize(,), wxTE_MULTILINE),
wxSizerFlags().Expand().Border(wxALL, )) // 2.5) Gratuitous test of wxStaticBoxSizers
(layout::begin(new wxStaticBoxSizer(new wxStaticBox(p, wxID_ANY, "A wxStaticBoxSizer"), wxVERTICAL))
(new wxStaticText(p, wxID_ANY, "And some TEXT inside it"), wxSizerFlags().Border(wxALL, ))
(layout::end), wxSizerFlags().Expand().Border(wxALL, )) // 2.7) And a test of wxGridSizer
(layout::begin(new wxGridSizer(, , ))
(new wxStaticText(p, wxID_ANY, "Label"),
wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL))
(new wxTextCtrl(p, wxID_ANY, "Grid sizer demo"),
wxSizerFlags().Align(wxGROW | wxALIGN_CENTER_VERTICAL))
(new wxStaticText(p, wxID_ANY, "Another label"),
wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL))
(new wxTextCtrl(p, wxID_ANY, "More text"),
wxSizerFlags().Align(wxGROW | wxALIGN_CENTER_VERTICAL))
(new wxStaticText(p, wxID_ANY, "Final label"),
wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL))
(new wxTextCtrl(p, wxID_ANY, "And yet more text"),
wxSizerFlags().Align(wxGROW | wxALIGN_CENTER_VERTICAL))
(layout::end), wxSizerFlags().Proportion().Expand().Border(wxALL, )) #if wxUSE_STATLINE
// 3) middle: create wxStaticLine with minimum size (3x3)
(new wxStaticLine( p, wxID_ANY, wxDefaultPosition, wxSize(,), wxHORIZONTAL),
wxSizerFlags().Expand())
#endif // wxUSE_STATLINE // 4) bottom: create two centred wxButtons
(layout::begin(new wxBoxSizer( wxHORIZONTAL ))
(new wxButton( p, wxID_ANY, "Two buttons in a box" ),
wxSizerFlags().Border(wxALL, ))[onclick = [=](wxCommandEvent& e) { delegate->OnClick(e); } ]
(new wxButton( p, wxID_ANY, "(wxCENTER)" ),
wxSizerFlags().Border(wxALL, ))
(layout::end), wxSizerFlags().Center())
(layout::end,
[=](wxSizer* s) {
p->SetSizer(s);
s->SetSizeHints(frame);
}); frame->Show(true);
return true;
}

zwx_helper将会在https://github.com/bbqz007/zhelper-wxWidgets/发布。

zwx_helper的更多相关文章

  1. zwx_helper 只用小括号()和中括号[ ] 轻松开发wxWidgets

    https://github.com/bbqz007/zhelper-wxWidgets https://github.com/bbqz007/zhelper-wxWidgets/tree/maste ...

  2. zqt_helper 轻松开发Qt5 Widgets应用

    目标: 1. 代码更加紧凑,所写即所到. 2. 代码层次更直观,直接反映界面窗口层次关系. 3. 不继承类,不重写虚函数,slot接收QEvent. 4. 简单写布局,忘掉api函数. 5. 免去一大 ...

随机推荐

  1. docker-compose中加入nginx 日志和部署下载

    服务器部署了nginx镜像,所以加入一个日志查看,添加一下静态页面下载. 1.查看nginx镜像怎么部署的 nginx: image: nginx ports: - '80:80' volumes: ...

  2. Linux bash篇,基本信息和变量

    1.shells目录       /etc/shells 2.查看用户所具有的shell    /etc/passwd 3.查看当前用户执行过的shell      ~/.bash_history 4 ...

  3. 使用nginx转换HTTPS流量

    背景 公司卖了一个产品给甲方,甲方要求部署后,要以https来访问.甲方提供了证书信息和私钥,记录一下部署过程. 实现 1.思路 在我们产品服务器上部署一个nginx.证书信息也放在这个服务器上.外界 ...

  4. Vue-CLI 3.x 部署项目至生产服务器

    本文已同步到专业技术网站 www.sufaith.com, 该网站专注于前后端开发技术与经验分享, 包含Web开发.Nodejs.Python.Linux.IT资讯等板块. 本教程主要讲解的是 Vue ...

  5. 盘点一下Github上开源的编程面试/学习相关的仓库

    转载自:JavaGuide 最近浏览 Github ,收藏了一些还算不错的 Java面试/学习相关的仓库,分享给大家,希望对你有帮助.我暂且按照目前的 Star 数量来排序. 本文由 SnailCli ...

  6. hive常用函数四

    字符串函数 1. 字符串长度函数:length 语法: length(string A) 返回值: int 说明:返回字符串A的长度 举例: hive> select length('abced ...

  7. alg-最长不重复子串

    class Solution { public: int lengthOfLongestSubstring(const std::string& s) { int max_length = 0 ...

  8. Python 操作mysql数据库之 SQLAlchemy 案例详解

      前言: 字段声明类型中,最右边的是数据库中对应的字段,我们依然可以使用,其左边的的 SQLAchemy 则是其自身封装的自定义类型. 本篇不会讲太多的理论知识,因为这个实用性更强,所以通篇全部都是 ...

  9. docker深入学习

    docker深入学习 一.容器的介绍和容器的发展史 为什么要学习容器? 在openstack之后,目前互联网最火热的技术莫过于docker容器了,早在2015年,京东技术备战双11就是使用了10万+D ...

  10. AJ学IOS(31)UI之Quartz2D图形上下文栈

    AJ分享,必须精品 首先,前面博客说过.qurza2d的上下文中有绘图信息和绘图的属性. 但是他是怎么绘制到上下午中的呢? 我们画图时候一半会用这三个步骤: (1)获取上下文 (2)绘图 (3)渲染 ...