2016-12-27 49 views
0

我想派生我自己的窗口小部件类,并将标准窗口小部件添加到此类中以创建复合窗口小部件。有没有人有如何做到这一点的例子或建议?例如,假设我想创建4个按钮的自定义复合小部件。我猜它类似于下面的代码:GTKMM/C++ 11:如何从其他小部件创建自定义复合小部件?

//First Question: Is this the best way to create composite widget? (see below) 

//Second Question: How do you make a widget container expand in 
// the horizontal direction while at the same time shrink in 
// the vertical direction? because i wanted the boxes to expand horizontally 
// to fill the window, and at the same time shrink to minimum width in the vertical 
// direction 


#include <iostream> 

using namespace std; 
#include <gtkmm.h> 

class MyWidget : public Gtk::Frame { 
    public: 
    MyWidget() { 
     add(m_hbox1); 
     m_hbox1.pack_start (m_vbox1, Gtk::PackOptions::PACK_SHRINK); 
     m_vbox1.pack_start (m_hbox2, Gtk::PackOptions::PACK_EXPAND_WIDGET); 
     m_hbox2.pack_start (m_btn_fwd, Gtk::PackOptions::PACK_EXPAND_WIDGET); 
     m_hbox2.pack_start (m_btn_play, Gtk::PackOptions::PACK_EXPAND_WIDGET); 
     m_hbox2.pack_start (m_btn_stop, Gtk::PackOptions::PACK_EXPAND_WIDGET); 
     m_hbox2.pack_start (m_btn_back, Gtk::PackOptions::PACK_EXPAND_WIDGET); 

     show_all_children(); 
    } 
    ~MyWidget() { 
    } 

    private: 

    Gtk::Box m_vbox1 {Gtk::ORIENTATION_VERTICAL}; 
    Gtk::Box m_hbox1 {Gtk::ORIENTATION_HORIZONTAL}; 
    Gtk::Box m_hbox2 {Gtk::ORIENTATION_HORIZONTAL}; 
    Gtk::Button m_btn_fwd {"Fwd"}; 
    Gtk::Button m_btn_back {"Back"}; 
    Gtk::Button m_btn_play {"Play"}; 
    Gtk::Button m_btn_stop {"Stop"}; 
}; 

class MyWindow : public Gtk::Window { 
    public: 
    MyWindow(string name) { 
     set_title(name); 
     add(m_vbox); 

     // Shrink in Vertical Direction 
     m_vbox.pack_start(m_mywidget, Gtk::PackOptions::PACK_SHRINK); 

     show_all_children(); 
    } 

    private: 
    Gtk::Box m_vbox  {Gtk::ORIENTATION_VERTICAL}; 
    MyWidget m_mywidget; 
}; 

int main(int argc, char *argv[]) 
{ 
    auto app = Gtk::Application::create(argc, argv, 
    "org.gtkmm.example.actionbar"); 

    MyWindow window {"Testing Custom Composite Widget"}; 

    // Shows the window and returns when it is closed. 
    return app->run(window); 
} 

回答

0

实验的几个星期之后,我的结论是,它能够更好地避免使用C++来从一个GTK控件::在继承以便创建一个复合构件。相反,最好在gktmm中创建一个纯粹的容器类的复合构件,即。不是从任何类派生出来的,并且重载C++ 11 Functor操作符来返回一个Gtk :: Box Widget,该对象的构造函数预先打包了Gtk :: Box Widget以及构建复合组件所需的所有Widget。例如:

using namespace std; 
#include <gtkmm.h> 
#include <iostream> 

//====================================================== 
// SearchBar: An Example GTKMM Composite Widget/wmoore 
//====================================================== 
class SearchBar { 
    public: 
    SearchBar(); 
    Gtk::Widget& operator()(); 

    public: 
    Gtk::Box box {Gtk::ORIENTATION_HORIZONTAL}; 
    Gtk::Label label {"search: "}; 
    Gtk::Entry entry; 
    Gtk::Button BtnOk{"find"}; 
    Gtk::Button BtnNext{">"}; 
    Gtk::Button BtnPrev{"<"}; 
}; 

inline SearchBar::SearchBar() { 
    box.pack_start(label); 
    box.pack_start(entry, Gtk::PACK_EXPAND_WIDGET); 
    box.pack_end(BtnNext); 
    box.pack_end(BtnPrev); 
    box.pack_end(BtnOk); 
} 

inline Gtk::Widget& SearchBar::operator()() { 
    return box; 
} 

class MyWindow : public Gtk::Window { 
    public: 
    MyWindow(string name) { 
     set_title(name); 
     add(m_vbox); 

     // Shrink in Vertical Direction 
     m_vbox.pack_start(m_searchbar(), Gtk::PackOptions::PACK_SHRINK); 
         // ^^^ NOTE use of C++11 functor operator "()" 
         // added to end of object name 
         // that makes it easy to tell difference between 
         // Gtk::Widget and Composite widget's built 
         // from many Gtk::Widget's 

     ////Example Connecting of Signals to composite widget: 
     // m_searchbar.BtnOk.signal_clicked.connect([]() { 
     //  cout << "clicked button!\n";}) 

     show_all_children(); 
    } 

    private: 
    Gtk::Box m_vbox  {Gtk::ORIENTATION_VERTICAL}; 
    SearchBar m_searchbar; 
}; 

int main(int argc, char *argv[]) 
{ 
    auto app = Gtk::Application::create(argc, argv, 
    "org.gtkmm.example.actionbar"); 

    MyWindow window {"Testing Custom Composite Widget"}; 

    // Shows the window and returns when it is closed. 
    return app->run(window); 
} 

之所以使用纯容器类而不是继承从基于GTK ::窗口小部件以创建复合插件如下:

(1)的部件API对gtkmm的非常多,而且往往隐藏您添加到您的复合控件中的任何新的公共方法,这些混乱的gtkmm控件方法可能不会使用任何方法。出于这样的原因。最好将所有容器小部件对象添加到类的公共部分,包括顶级小部件框。您仍然可以访问每个对象窗口小部件的所有方法,而无需使用gtkmm api混乱。 (2)从Gtk :: Widget继承你的类在多态行为方面并没有真正有用,因为复合构件的构件已经是从Gtk :: Widget派生出来的多态对象。将顶层窗口小部件框添加到父窗口小部件时将复合窗口小部件的所有子窗口小部件添加到父窗口小部件的子窗口列表中。因此,真的不需要为复合控件容器设置多态行为。 (3)如果您需要从Gtk:Widget派生的复合窗口小部件,那么可以很容易地将它放在它的类封装器中,该类封装器将它转换回从Gtk :: Widget派生的类。事实上,这一步很容易通过模板类包装器的oneline实例化完成。我想到做这件事的唯一原因是将一个组件插回到glade中(短于Glade Gui认识到C++ 11 functor操作符是返回复合小部件的顶级小部件的标准方法(可能为glade支持)未来愿望清单...))

+0

'运算符Gtk :: Widget&'比'operator()'更合适' –