QSharedPointer
可以使用QSharedPointer进行管理,初始化方式为
QSharedPointer<类名> A; // 创建对象
A = QSharedPointer<类名>(new 类名(参数), &QObject::deleteLater); // 初始化
具体的可以查看qt文档QSharedPointer Class | Qt Core 5.15.17
QSharedPointer属于智能指针,他是一个共享指针,会在父类界面析构时,自动释放指针的内存,也就是说会在父界面关闭时将弹出的界面也一起关闭掉。
但是有一个问题,如果我弹出的界面,我自己关闭了,此时指针指向空,但是QSharedPoint并不会自动检测指针内部情况,也就是说,他不知道指针已经为空,因此在关闭父界面时,会尝试释放指向为空的指针,会报错。
怎么解决呢?
目前我对于继承自QDialog的弹窗已经有了解决办法,在创建弹窗的界面里,连接弹窗关闭的信号
// 假设指针为A
connect(A.get(), &QDialog::finished, [&] {A.clear();});
这样子,就可以在弹窗关闭的时候,手动释放掉指针。
(目前我对于继承QWidget的弹窗没有具体的解决办法,如果要使用QSharedPoint管理,最好继承自QDialog,或者就只能手动去自己编写管理界面的代码,很繁琐会增加大量代码量)
多个主题框架一样的弹窗
方法一:widget加载
我们在编写程序时,有时会遇到这样的情况:同一个程序有n多个弹窗,这些弹窗底部的按钮,顶部的标题栏基本都一样,只有中间部分的内容不一样。
这个时候,我刚开始傻傻地还一个一个ctrl c、ctrl v,这样不仅很麻烦,而且代码也不美观,一样的代码每个弹窗都得写一份,但是记住c++的特性:继承、封装、多态!
面对上述这种情况,我们可以先创建一个主题框架(如包含标题栏、底部按钮、中间一个空白的添加了布局的widget)的ui界面,可以根据自己的需求对标题、按钮等在构造函数或者写一个函数中通过子类调用来定义。
这就不需要例子了吧o.O
至于为什么中间要个widget呢,因为在布局中有一个函数:addWidget,在widget中也有一个函数:void QWidget::setupUi(QWidget *widget) // 为指定的widget设置一个ui界面,所以我们需要一个widget。
因此,我们继续在基类中写一个函数,用来给widget中的布局设置addWidget
protected:
template<typename UI>
void setupUi(UI& contentUi, bool resize = true) {
contentView = new QWidget(baseTips.widget_tips);
baseTips.verticalLayout_tips->addWidget(contentView);
contentUi.setupUi(contentView); // 给contentView设置contentUi界面
if (resize) {
resizeWindow(); // 自己根据需求考虑是否需要根据内部内容改变弹窗大小
}
}
protected:
Ui::BaseTips baseTips;
QWidget *contentView; // dialog中的切换界面
这一下基本就完成了,只需用在子类中调用setupUi(子类的ui)即可,特殊情况下(如有固定的widget加载),可以重载一个,只需用直接加入指定的widget(代码中contentView)
template<typename W>
void setupUi(W* contentWidget, bool resize = true) {
contentView = contentWidget;
baseUi.content_layout->addWidget(contentView);
if (resize) {
resizeWindow();
}
}
同样的,如果要连续切换,但是一直创建对象很麻烦,也可以通过删除加载的子类ui,重新加载新的子类ui解决:这里举例是如何删除加载的ui的
void deleteUi() {
if (contentView) {
baseTips.verticalLayout_tips->removeWidget(contentView);
delete contentView;
}
}
至此,应该能完成大部分的工作,如有错误或纰漏请指出。
方法二:QStackedWidget
在Qt中有这么一个控件:StackedWidget,其作用是切换此容器内的界面,跟上一个方法类似,先创建一个主体框架,但是内部显示的控件换成StackedWidget,然后在其中将需要的界面全部加载进去,根据需求一个一个调出来就是了(个人不太推荐这种方法,因为这往往意味着同一个弹窗,他所占的内存远远大于第一种方法)
这里就不举例了(因为懒),官方的StackedWidget实在是不好用,不得不说一句我主管yyds自己写的框架!
emmm,暂时就这些吧,欢迎探讨交流!