wxWidgets Programming: Sizer, Frame and Panel

wxwidget-gui-library 个人感觉在 编程时,一开始最难于理解和使用的就是,尤其是在与各种控件、Panel嵌套搭配的时候,包括对控件间隙以及父窗口大小发生改变时各个控件的变化定义等。在网上发现这篇文章非常详细的总结了, Frame和Panel的关系并通过简单的实例深入浅出地讲解了这一部分,转载在此供大家参考,如果你有相关技术问题或者开发心得也可以发评论参加讨论。

[原文如下] 最近在研究跨平台的C/C++ GUI库,基本说来功能强大,稳定且开源的库就是了,关于他们之间具体的比较详见《WxWidgets Compared To Other Toolkits》。 N年以前研究过一段时间的代码,不过主要因为其在开发商用软件还是要一定的license费用,所以不能说是真正的免费跨平台。 则是一套免费开源的跨平台C++ GUI库,它的一个特点就是可以转换为native 的api图形界面。就是说用同样的代码,在平台看起来就是window风格的,在X 平台看起来就是风格的。

代码和命名上,比较接近 MFC, 但是它的物件封装比 MFC 要好。一般知名的 MFC 程式都会选择用 改写,来快速移植原程式到其他平台,例如 eMule 用 移植出 aMule, xMule。 在GUI的控件和窗口布局上可以使用坐标,更多且更方便的是用来布局。就像是一个布局用的容器,只要指定了 的布局方式,然后往里面一个一个的插入待布局的元素就可以了,类似于的slot。而且用有一个最大的好处就是内部的元 素可以根据窗口的变化自动的安装指定模式改变自身的大小。 最初根据官方文档用panel和布局的时候总是发现有问题,拷贝过来的示例代码也不同于文档描述的显示界面。经过一段时间的代码试验,找到了一些思路,现分析如下。

首先简要介绍下frame,panel和。 Panel是一个用来控制布局的窗口,通常放在frame里面。类wxPanel继承于父类wxWindow,但重载了父类的一些函数,主要用来控制对话框的外观和功能。 If the wxPanel is the only child window of the frame then it will automatically take up the entire client area of the frame. App类 (简单的初始化窗口,类似代码不再显示)

bool testApp::OnInit() {

testFrame* dlg = new testFrame(0L, _(” Application Template”));

dlg->SetIcon(wxICON(aaaa)); // To Set App Icon

dlg->Show();

return true; }

框架类: testFrame::testFrame(wxFrame *dlg, const wxString &title):

wxFrame(NULL, -1, title, wxPoint(-1, -1), wxSize(300, 200)) {

wxPanel *panel = new wxPanel(this, -1); //新建一个panel

wxButton *ok = new wxButton(panel, -1, wxT(”Ok”)); //在panel上画一个按钮 }

正常的显示结果,如图 

 

 

 

 

 

 

 

在框架类中添加一行 wxPanel *panel = new wxPanel(this, -1);

wxButton *ok = new wxButton(panel, -1, wxT(”Ok”));

wxButton *cancel = new wxButton(panel, -1, wxT(”Cancel”)); 运行结果,发现显示没有变化 稍微修改一下,加一个坐标

wxPanel *panel = new wxPanel(this, -1);

wxButton *ok = new wxButton(panel, -1, wxT(”Ok”));

wxButton *cancel = new wxButton(panel, -1, wxT(”Cancel”),wxPoint(30,30)); 结果如图

 

 

 

 

 

 

由此可以分析知道在panel上的控件都是基于坐标进行定位的,相同坐标的控件覆盖顺序是前面的覆盖后面的 下面我们再进一步,添加一个垂直的

wxPanel *panel = new wxPanel(this, -1);

wxButton *ok = new wxButton(panel, -1, wxT(”Ok”));

wxButton *cancel = new wxButton(panel, -1, wxT(”Cancel”),wxPoint(30,30));

wxBoxSizer* = new wxBoxSizer( wxVERTICAL ); ->Add(panel); SetSizer(); 运行结果如图

 

黑底的部分是frame的底色白色的部分则是使用下的panel部分,可以看到panel的大小也改变了,不再占据整个frame的位置,而是它包含控件的总面积 让我们试试不包含panel,而是换为控件button。 ->Add(ok); ->Add(cancel); panel->SetSizer(); 结果如图 注意这里用的是panel->SetSizer()而不是SetSizer()。

 

 

 

 

 

 

因为是一个隐式的布局对象,而panel可以作为 底色单独显示出来。panel->SetSizer()就好比先用对包含的元素重新布局,然后把布好局的元素重新印到panel面板上。 SetSizer()隐式调用的是this->SetSizer(),这里的this对象是frame的实例,而两个button的父窗口是 panel,所以如果这里调用SetSizer(),则frame重新布局为一个隐式的布局对象,显示结果将会变的很奇怪。 接下来我们换一下,用dialog替换frame,构造函数还是用最基本的一个button testDialog::testDialog(wxDialog *dlg, const wxString &title): wxDialog(NULL, -1, title, wxPoint(-1, -1), wxSize(300, 200)) {wxPanel *panel = new wxPanel(this, -1);wxButton *ok = new wxButton(panel, -1, wxT(”Ok”));} 显示结果很奇怪,如图 一样的构造函数代码,只是继承的父类不同就产生了不同的结果。

 

 

 

 

 

 

其原因是因为新创建的Frame没有关联的子窗口panel,所以一旦new了一个 panel,它会自动和父窗口frame关联,并自动填充整个frame的位置。但是新创建的dialog对话框自己就有一个panel,再new一个新 的子窗口panel并不会自动填充dialog的位置,而是覆在原来的panel上面。把两个panel都加上颜色分辨的比较清楚

wxPanel *panel = new wxPanel(this, -1); //wxButton *ok = new wxButton(panel, -1, wxT(”Ok”));

wxColour col1,col2; col1.Set(wxT(”#4f5049″));

col2.Set(wxT(”#7d7ded”));

this->SetBackgroundColour(col1);

panel->SetBackgroundColour(col2); 结果如图 可以清楚的看到,下面的大框就是对话框的底色,左上角的小篮框就是new出来的panel。因此,要在对话框中实现上述效果,只要直接使用this指针控件的父窗口就可,而不需要重新new一个panel。

 

 

 

 

 

 

wxButton *ok = new wxButton(this, -1, wxT(”Ok”));

wxButton *cancel = new wxButton(this, -1, wxT(”Cancel”),wxPoint(30,30));

wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );

wxBoxSizer* bottomSizer=new wxBoxSizer(wxHORIZONTAL);

wxButton *h1 = new wxButton(this, -1, wxT(”h1″));

wxButton *h2 = new wxButton(this, -1, wxT(”h2″));

bottomSizer->Add(h1); bottomSizer->Add(h2);

topSizer->Add(ok); topSizer->Add(cancel); topSizer->Add(bottomSizer); SetSizer(topSizer); 运行结果如图 这里用了2个,一个垂直的topSizer包含了一个水平的 bottomSizer.topSizer->Add(bottomSizer);这里所有的控件都是基于对话框自己的panel,他们的父窗口都 是this指针。

 

 

 

 

 

如果控件是在不同的panel上面,则代码需要修改了 wxPanel *panel = new wxPanel(this, -1); //一个新的panel wxButton *ok = new wxButton(this, -1, wxT(”Ok”)); wxButton *cancel = new wxButton(this, -1, wxT(”Cancel”),wxPoint(30,30)); wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer* bottomSizer=new wxBoxSizer(wxHORIZONTAL); wxButton *h1 = new wxButton(panel, -1, wxT(”h1″)); wxButton *h2 = new wxButton(panel, -1, wxT(”h2″)); //button都在新的panel上 bottomSizer->Add(h1); bottomSizer->Add(h2); topSizer->Add(ok); topSizer->Add(cancel); panel->SetSizer(bottomSizer);//这里panel要用来重新布局 topSizer->Add(panel);//add的是panel而不是 SetSizer(topSizer); 运行结果基本和上图一样。比较两段代码可以看到,如果控件是属于不同的panel,用组合起来的话不能直接add 了,就像前面所说的,只是一个隐式的布局对象,如果不放在panel上的话是无法正常显示的。不同panel的不能直接相 互包容,必须通过panel设置模式,上层再包容panel来进行组合布局。

 

总结一下:

1.frame默认没有自己的子窗口panel,new出来的唯一子窗口panel将会占据它的全面空间

2.对话框默认有自己的子窗口panel,new出来的额外panel可以通过来组合布局,否则会以最小形式直接覆盖在原panel上面。

3.可以Add 或panel.只有所有元素属于同一个panel的才能相互直接add,否则应该待包含的panel应该调用SetSizer方法来重新实例化自己的布局,然后用上层来包含这个panel。

总的来说,用实现GUI的界面还是很直观的,基本可以说是有了实例化的对象就可以看到图形。对习惯了MFC中对象和资源分开匹配的开发者来说,实在是一个惊喜,特别是有了布局容器的存在,整体的设计将会更加方便。

本站所有文章若非注明均为原创,转载请保留作者和出处www.yichao.info

Share and Enjoy:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • Live
  • MySpace
  • RSS
  • Slashdot
  • Technorati
  • TwitThis

Related posts:

  1. A rough guide for wxWidgets programming
  2. Book: Cross-Platform GUI Programming with wxWidgets (Bruce Perens)(含中英文版本下载地址)
  3. Using XRC in wxWidgets based Application for UI design
  4. wxWidget Layout Algorithm Demo - BoxPlanner
  5. Python Programming – Sqlite for data persistence
  6. Python programming- List extend() and append()
  7. Core Python Programming(1) - Basic
  8. Code::Blocks IDE in openSUSE 11.1编译和安装指南
  9. Debian Lenny编译wxWidgets与Code::Blocks SVN版
  10. wxWidget 类型转换(wxString, wxdatatime)

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

Contact us

Admin: Bryan Wu