zoukankan      html  css  js  c++  java
  • zwx_helper, 让wxWidgets界面开发变轻松。

    通过重载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...	F1");
        file_menu->Append(LAYOUT_TEST_SIZER, "Test wx&FlexSizer...	F2");
        file_menu->Append(LAYOUT_TEST_NB_SIZER, "Test &notebook sizers...	F3");
        file_menu->Append(LAYOUT_TEST_GB_SIZER, "Test &gridbag sizer...	F4");
        file_menu->Append(LAYOUT_TEST_SET_MINIMAL, "Test Set&ItemMinSize...	F5");
        file_menu->Append(LAYOUT_TEST_NESTED, "Test nested sizer in a wxPanel...	F6");
        file_menu->Append(LAYOUT_TEST_WRAP, "Test wrap sizers...	F7");
    
        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(2);
        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, 5));
        topsizer->Add(
            new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_LEFT)." ),
            wxSizerFlags().Align(wxALIGN_LEFT).Border(wxALL & ~wxBOTTOM, 5));
        topsizer->Add(
            new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_CENTRE_HORIZONTAL)." ),
            wxSizerFlags().Align(wxALIGN_CENTRE_HORIZONTAL).Border(wxALL & ~wxBOTTOM, 5));
    
        // 2) top: create wxTextCtrl with minimum size (100x60)
        topsizer->Add(
            new wxTextCtrl( p, wxID_ANY, "My text (wxEXPAND).", wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE),
            wxSizerFlags(1).Expand().Border(wxALL, 5));
    
        // 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, 30));
        topsizer->Add(
            statsizer,
            wxSizerFlags(1).Expand().Border(wxALL, 10));
    
        // 2.7) And a test of wxGridSizer
        wxGridSizer *gridsizer = new wxGridSizer(2, 5, 5);
        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(1).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(1).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(1).Expand().Border(wxALL, 10));
    
    
    #if wxUSE_STATLINE
        // 3) middle: create wxStaticLine with minimum size (3x3)
        topsizer->Add(
            new wxStaticLine( p, wxID_ANY, wxDefaultPosition, wxSize(3,3), 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, 7));
        button_box->Add(
            new wxButton( p, wxID_ANY, "(wxCENTER)" ),
            wxSizerFlags().Border(wxALL, 7));
    
        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...	F1", &MyFrame::TestMenuCommand, frame)
                        (LAYOUT_TEST_SIZER, "Test wx&FlexSizer...	F2", &MyFrame::TestMenuCommand, frame)
                        (LAYOUT_TEST_NB_SIZER, "Test &notebook sizers...	F3", &MyFrame::TestMenuCommand, frame)
                        (LAYOUT_TEST_GB_SIZER, "Test &gridbag sizer...	F4", frame, [=](wxCommandEvent& event) { frame->TestMenuCommand(event); })
                        (LAYOUT_TEST_SET_MINIMAL, "Test Set&ItemMinSize...	F5")
                        (LAYOUT_TEST_NESTED, "Test nested sizer in a wxPanel...	F6", frame, [=](wxCommandEvent& event) { sptr_delegate->TestMenuCommand(event); })(LAYOUT_TEST_WRAP, "Test wrap sizers...	F7")
                        (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, 5))
            (new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_LEFT)." ),
            wxSizerFlags().Align(wxALIGN_LEFT).Border(wxALL & ~wxBOTTOM, 5))
            (new wxStaticText( p, wxID_ANY, "An explanation (wxALIGN_CENTRE_HORIZONTAL)." ),
            wxSizerFlags().Align(wxALIGN_CENTRE_HORIZONTAL).Border(wxALL & ~wxBOTTOM, 5))
    
        // 2) top: create wxTextCtrl with minimum size (100x60)
            (new wxTextCtrl( p, wxID_ANY, "My text (wxEXPAND).", wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE),
            wxSizerFlags(1).Expand().Border(wxALL, 5))
    
        // 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, 30))
                (layout::end), wxSizerFlags(1).Expand().Border(wxALL, 10))
    
        // 2.7) And a test of wxGridSizer
            (layout::begin(new wxGridSizer(2, 5, 5))
                    (new wxStaticText(p, wxID_ANY, "Label"),
                    wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL))
                    (new wxTextCtrl(p, wxID_ANY, "Grid sizer demo"),
                    wxSizerFlags(1).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(1).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(1).Expand().Border(wxALL, 10))
    
    
    #if wxUSE_STATLINE
        // 3) middle: create wxStaticLine with minimum size (3x3)
            (new wxStaticLine( p, wxID_ANY, wxDefaultPosition, wxSize(3,3), 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, 7))[onclick = [=](wxCommandEvent& e) { delegate->OnClick(e); } ]
                (new wxButton( p, wxID_ANY, "(wxCENTER)" ),
                wxSizerFlags().Border(wxALL, 7))
                (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/发布。

  • 相关阅读:
    四则运算在线答题dos
    动手动脑11.11
    Java编程中关于异常处理的10个要点
    java第五周课后作业1
    java静态初始化块的执行顺序
    java工程项目作业1
    十一Java作业三
    Linux运维笔记(一)网络基础知识
    分布式笔记(二)一致性协议
    分布式笔记(一)分布式构架概述
  • 原文地址:https://www.cnblogs.com/bbqzsl/p/12822071.html
Copyright © 2011-2022 走看看