0. 课堂视频
状态栏通常被设计成不需要接收用户输入的“静态组件”,是一种常用的,且比较简单的图形界面组件。
1. 创建状态栏
通常在框架主窗口(用户自己写,或IDE向导生成的wxFrame的派生类)的构造函数中,创建状态栏,并指定包含几个子面板(fields)。
框架窗口(也就是程序的主窗口对象)将记住、持有该函数内创建的状态栏。为方便操作,框架窗口基类(wxFrameBase) 提供了本课所学的,与状态栏相关的几个方法,但实际上,这些方法最终涉及状态栏的操作,都由前述的状态栏完成。
方法原型:
virtual wxStatusBar* wxFrame::CreateStatusBar ( int number = 1,
long style = wxSTB_DEFAULT_STYLE,
wxWindowID id = 0,
const wxString & name = wxStatusBarNameStr
);
使用示例:
实际调用时,可以忽略多数入参,包括返回值(因为如前所述,当前框架窗口负责持有)。
// 以下代码示例创建一个状态栏,并设置包含3个子面板
CreateStatusBar(3);
2. 设置状态栏子面板文本内容
方法原型:
virtual void SetStatusText (const wxString &text, int number=0);
- text 指定文本内容
- number 指定第几个子面板,次序从 0 开始
使用示例:
以下方法设置第0个面板显示 “d2school.com”:
SetStatusText(wxT("d2school.com"), 0);
3. 设置一组面板的宽度
方法原型:
virtual void SetStatusWidths (int n, const int *widths_field);
- n 指定 widths_fields 指针指向的(整数)元素个数;
- widths 包含从第一个开始的各面板新宽度;
使用示例:
int widths[] {120, 140, 80};
SetStatusWidths(WXSIZEOF(widths), widths);
由于“数组退化”,此类以“数组”为入参的函数多数都需要带上另一个参数,用于指明数组(将退化为指针)的实际元素个数。此时可以使用 C++2017 新标引入 std::size(),也可以使用 wxWidgets 提供的工具宏 WXSIZEOF()。
上例所设置的三个宽度,都是固定宽度,所设置的三个面板在程序时,宽度固定的。wxWidgets 也支持为状态栏面板设置“动态宽度”,或称为 “比例宽度”,方法就是将指定面板宽度设置为负数。
实际执行效果:当状态栏跟随所在的窗口自动拉伸(宽度变大变小)时,会首先为设为固定宽度的面板,分配固定宽度,余下宽度,交给设置了动态(也就是负数)宽度的面板以负数的绝对值按比例分配。比如有两个面板设置成动态宽度,一为-1,二是-2,则后者实际分配的宽度是前者的两倍。
假设状态栏当前总宽度为 100,已知它有三个子面板,一个使用固定宽度为40,二个使用动态宽度为-1,三个为-2,则此时三者宽度分别为:
- 面板一:40(固定值)
- 面板二:20(余下宽度的三分之一,(100-40)*1÷3)
- 面板三:40(余下宽度的三分之二,(100-40)*2÷3)
4. 设置框架窗口默认状态面板
定义:采用框架窗口作程序主窗口时,框架窗口需要占用状态栏上的一个面板,用来显示诸如菜单项、工具按钮的提示。这个面板就叫默认状态面板。
wxWidgets 默认使用第一个子面板作为默认状态面板,可以通过框架窗口的以下方法来加以修改:
SetStatusBarPane(int n); // n 为面板次序号,从0开始
以下是在主框架窗口的构造过程中,多个状态栏相关方法的综合应用的示例:
CreateStatusBar(3); // 创建状态栏,含三个子面板
// 分别设置三个子面板的显示内容
SetStatusText(wxT("第2学堂 | d2school"), 0);
SetStatusText(wxbuildinfo(short_f), 1);
SetStatusText(_("Hello Code::Blocks user!"), 2);
// 一次性设置三个子面板的宽度,最后一个为动态宽度
int widths[] = {140, 140, -1};
int n = std::size(widths); // 使用 C++ 17 新标提供的方法
SetStatusWidths(n , widths);
SetStatusBarPane(2); // 设置第3个面板,也就是最后一个面板为默认面板
5 状态栏实际应用
在状态栏上显示内容,无需涉及窗口的 OnPaint() 事件,而是直接在鼠标移动事件的响应函数中,先依据当前鼠标坐标值,组装出文本内容(wxString),然后直接设定:
void HelloStatusBarFrame::OnMontion(wxMouseEvent& event)
{
xPos = event.GetPosition().x;
yPos = event.GetPosition().y;
//// 以下是新增内容 ////
wxString info;
info << xPos << wxT(" | ") << yPos;
SetStatusText(info, 0);
//// 新增内容结束 ////
this->Refresh();
}
运行效果:
6 更多知识
搜索 wxStatusBar 即可进入 wxWidges 官方文档中的状态栏类参考文档页面。