使用wxBoxSizer编程(按照官方文档翻译,如有不当之处,恕请指正!)
boxsizer基本思想就是让一个窗口的几何布局变得非常简单,比较典型的就是只有一行或者一列,或者是几层结构。
举个例子,假如我们要创建一个顶部为文本框,底部为两个按钮的对话框。我们可以把这个对话框看作是具有两层结构的列,顶层的列可以看做是上面为文本框下变为按钮,底层的列可以看做是左侧为ok按钮,右侧为cancel按钮。在很多情况下(特别是Unix下的对话框和正常的框架)主窗口可以根据根据用户要求和子控件的大小来自由调整大小。在我们举得例子中,我们希望文本框能够随着对话窗口大小的改变而改变,而按钮大小却固定不变。另外,所有的控件要使用细边框以保证对话框看起来比较舒服-更糟的要求是-当对话框窗口大小改变时,按钮要始终保持居中显示。
Boxsize有一个特性就是它可以朝着两个方向(宽和高)调整大小,但是子控件依照主要调整方向(横向为行)来不均衡分布。在我们举的例子中,我们希望垂直容器的比重扩大只是针对文本区域,而不是按钮区域。而这是由向容器中添加窗口(或另外一个容器)时的比例参数决定的,此参数被当做比重因子,可以设为0或者大于0,设为0就意味着窗口大小不会改变。如果好几个窗口的proportion参数值都大于0,那么proportion参数值要相对于所有窗口的值之和来生效。如果我们添加两个proportion参数值为1的窗口,那么两个窗口大小变化时变化的都一样大,而且总大小都是容器的一半大小。那当列容器的宽度发生改变时我们该怎么办?这个行为是由flags参数(Add()函数的第二个参数(从0开始编号))控制的:0或空指示着窗口将保持原有大小,wxGROW(同wxEXPAND)指示强制窗口跟随容器大小的改变而改变,wxSHAPED参数告诉该窗口按比例调整大小,即保持原有的宽高比。当未使用wxGROW参数时,该窗口的大小可以在可用的空间内指定。wxALIGN_LEFT,wxALIGN_TOP,wxALIGN_RIGHT,wxALIGN_BOTTOM,wxALIGN_CENTER_HORIZONTAL和wxALIGN_CENTER_VERTICAL按照字面意思描述的那样来对其。WxALIGN_CENTRE(同wxALIGN_CENTER)被定义做(wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL)。默认的对齐方式是wxALIGN_LEFT|wxALIGN_TOP。
如前所述,任何属于容器的窗口可能都会有边框,可以使用wxTOP,wxLEFT,wxLEFT,wxRIGHT和wxBOTTOM来指定4条边的哪一条使用边框,或者用wxALL来设置全部4个方向都有边框(你也可以用wxNORTH,wxWEST等替代)。可以用二进制|运算符把边框标志位和对齐标志位或在一起,用作上面提到的的Add()函数的第三个参数。边框的大小可以用Add()函数的第四个参数来设置。这样,整个容器的行为和子控件就都可用Add()函数的后三个参数来控制。
//示例代码
MyDialog::MyDialog(wxFrame *parent, wxWindowID id, const wxString &title ) : wxDialog(parent, id, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); // create text ctrl with minimal size 100x60 topsizer->Add( new wxTextCtrl( this, -1, "My text.", wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE), 1, // 垂直方向可拉伸 wxEXPAND | // 水平方向自动填充 wxALL, // 四周都有边框 10 ); // 边框宽度为10 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL ); button_sizer->Add( new wxButton( this, wxID_OK, "OK" ), 0, // 水平不可拉伸 wxALL, // 四周边框 10 ); // 边框宽度为10 button_sizer->Add( new wxButton( this, wxID_CANCEL, "Cancel" ), 0, // 水平不可拉伸 wxALL, // 四周边框 10 ); // 边框宽度为10
topsizer->Add( button_sizer, 0, // 横向不可拉伸 wxALIGN_CENTER ); //无边框,居中对齐 SetSizer( topsizer ); // 设置topsizer作为布局 topsizer->SetSizeHints( this ); // 设置大小为最小尺寸 }
另外还可以通过wxSizeFlags的方法来为wxSizer指定flags参数。这个类极大的减轻了向wxSizer传递参数的负担。以下代码就是前面那个例子用wxSizeFlags的实现方式:
MyDialog::MyDialog(wxFrame *parent, wxWindowID id, const wxString &title ) : wxDialog(parent, id, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); topsizer->Add( new wxTextCtrl( this, -1, "My text.", wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE), wxSizerFlags(1).Align().Expand().Border(wxALL, 10)); wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL ); button_sizer->Add( new wxButton( this, wxID_OK, "OK" ), wxSizerFlags(0).Align().Border(wxALL, 10)); button_sizer->Add( new wxButton( this, wxID_CANCEL, "Cancel" ), wxSizerFlags(0).Align().Border(wxALL, 10)); topsizer->Add( button_sizer, wxSizerFlags(0).Center() ); SetSizer( topsizer ); topsizer->SetSizeHints( this );