在开始主题前,先看一个 C++ 例子:- #include <iostream>
- struct Data
- {
- int a;
- int b;
- };
- // 注意这里
- struct Data *s;
- void doSome()
- {
- Data k;
- k.a = 100;
- k.b = 300;
- // 注意这里,会出大事
- s = &k;
- }
- int main()
- {
- // 先调用了函数
- doSome();
- // 再输出 Data 结构体的内容
- std::cout << "a = " << s->a << '\n';
- std::cout << "b = " << s->b << '\n';
- return 0;
- }
复制代码 应用程序窗口继承了 QMainWindow 类,因为这个类比较方便构建菜单栏、工具栏、状态栏、停靠栏。咱们用它来创建一个菜单栏对象(QMenuBar),然后添加一个叫“应用程序”的菜单(QMenu)。
“应用程序”菜单的前两个菜单项是普通的 action,第三个是 QWidgetAction 对象。在 new 出 QWidgetAction 后,先初始化一下 QSpinBox 组件,然后调用 setDefaultWidget 方法,这样 QSpinBox 组件就能显示在菜单项上了。
在 main 函数中显示主窗口。- a = -858993460
- b = -858993460
复制代码 好了,见证奇迹的时候到了,看看效果。

另一种用法,就是从 QWidgetAction 类派生。然后重写这个方法:- void doSome()
- {
- static Data k;
- k.a = 100;
- k.b = 300;
- // 注意这里,会出大事
- s = &k;
- }
复制代码 parent 是父级对象,由调用者传递,这取决于这个自定义的 action 用在什么容器上了,如果用在菜单上,就是 QMenu 对象。返回值就是创建的自定义组件了。
另外,如果在析构自定义组件时有特殊处理,还可以重写 delete 方法。widget 参数是要被删除的自定义组件实例。如果无其他要实现的需求,没必要重写它。
下面咱们来个示例:自定义组件做个带三个滑块的界面。组件名称为 CustWidget,基类是 QFrame。选择 QFrame 作为基类是方便设置边框。- #include <iostream>
- class Test
- {
- public:
- Test()
- {
- std::cout << "Test 构造函数 ..." << std::endl;
- }
- ~Test()
- {
- std::cout << "Test 析构函数 ..." << std::endl;
- }
- int a,b;
- };
- // 注意这里
- Test *s;
- void doSome()
- {
- Test k;
- k.a= 100;
- k.b = 300;
- // 注意这里,会出大事
- s = &k;
- }
- int main()
- {
- // 先调用了函数
- std::cout << "调用doSome函数前\n";
- doSome();
- std::cout << "调用doSome函数后\n";
- // 再输出a、b的内容
- std::cout << "a = " << s->a << '\n';
- std::cout << "b = " << s->b << '\n';
- return 0;
- }
复制代码 滑块条是 QSlider 组件,它默认的方向是垂直的,所以要将方向设定为水平。自定义组件还用到了 QFormLayout 类,它是布局类,类似 HTML Form 元素的布局方式,即表单。一般分为两列,左列是字段标题,右列是字段内容。
CustWidget 组件定义好了,接下来就是 MyWidgetAction 类,派生自 QWidgetAction。- Test 构造函数 ...
- Test 析构函数 ...
- 调用doSome函数后
- a = -858993460
- b = -858993460
复制代码 整体逻辑很简单,就是返回 CustWidget 的实例。
然后咱们在前面 QWidgetAction 的示例上再添加一个菜单项,使用咱们刚定义的 MyWidgetAction。- void doSome()
- {
- Test *k = new Test;
- k->a = 100;
- k->b = 300;
- // 复制的是地址,不是对象
- s = k;
- }
复制代码 最后,咱们来看看效果。

这效果不错吧。
好了,今天就水到这里了,有空咱们继续聊。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |