Qt Plugin插件开发指南(3)- 插件中窗体的显示
Date | Author | Version | Note |
---|---|---|---|
2021.09.01 | Dog Tao | V1.0 | 整理后发表。 |
2021.09.10 | Dog Tao | V1.1 | 增加了“作为模态对话框显示”的说明。 |
概述
在使用QtPlugin机制开发插件时,有时候为了调试或者控制方便,会在插件中设置一个接口调用内嵌的窗体,并在此窗体上完成一些与插件相关的设定与调试功能。笔者的开发的插件项目,一般会预留一个获取面板的接口,用于获取内置的窗体。接口形式一般如下所示:
virtual QWidget *GetLogPanel(QWidget *parent = nullptr) = 0;
调用此接口会获得一个QWidget实例,它的父类可以由参数parent指定。获取到这个实例后,一般有两种显示途径,其一是调用show()方法作为独立窗体显示,其二是将其作为控件添加到父窗体布局中。
作为独立窗体显示
如果需要作为独立窗体显示,如果不继承父类窗体,则可以直接调用show()
方法,但这样做可能会导致此窗体没有继承父类窗体的一些样式设定,导致不同窗体的风格出现差异。示例如下:
如果继承父类,需要先设置窗体的Flag为Window,否则*“Non-window widgets are child widgets, displayed within their parent widgets.”*,即窗体只能在它们的父类窗体中显示(背景透明直接覆盖在父窗体上)。示例如下:
因此可用的代码示例如下:
QWidget *panel = logSystem->GetLogPanel(this);
panel->setWindowFlags(Qt::Window);
panel->show();
作为内嵌控件显示
如果作为内嵌控件显示,则将其视为普通QWidget
实例添加到窗体布局中即可。如果父窗体仍然是一个QWidget
实例,应当注意它如果作为独立窗体显示,也需要为其设置setWindowFlags(Qt::Window)
,否则父窗体也无法显示。如果父窗体是一个QDialog
实例,则可以直接作为独立窗体显示。示例如下:
QVBoxLayout *vBoxLayout_1 = new QVBoxLayout();
vBoxLayout_1->addWidget(logSystem->GetLogPanel());
QVBoxLayout *vBoxLayout_2 = new QVBoxLayout();
vBoxLayout_2->addWidget(new QPushButton(tr("Function 1")));
vBoxLayout_2->addWidget(new QPushButton(tr("Function 2")));
vBoxLayout_2->addWidget(new QPushButton(tr("Function 3")));
vBoxLayout_2->addWidget(new QPushButton(tr("Function 4")));
vBoxLayout_2->addWidget(new QPushButton(tr("Function 5")));
QHBoxLayout *hBoxLayout_1 = new QHBoxLayout();
hBoxLayout_1->addLayout(vBoxLayout_1);
hBoxLayout_1->addLayout(vBoxLayout_2);
QDialog *dialog = new QDialog(this);
dialog->setLayout(hBoxLayout_1);
dialog->show();
显示效果如下:
作为模态对话框显示
一些时候,我们需要将插件内置窗体作为模态对话框显示,其中又主要分为如下两种情况。
不阻塞线程显示
不阻塞线程显示的窗体始终置顶,但不影响其他窗体弹出显示,例如有几个窗体需要依次显示,这几个窗体会同时弹出。此时可以直接设置QWidget控件的模态,然后调用show()
方法即可。如果内嵌窗体已经设置了父窗体,则应使用Qt::WindowModal
:
QWidget *widget = pluginManager->GetPanel(parent);
widget->setWindowModality(Qt::WindowModal);
widget->show();
如果内嵌窗体没有设置父窗体,则应使用Qt::ApplicationModal
:
QWidget *widget = pluginManager->GetPanel(nullptr);
widget->setWindowModality(Qt::ApplicationModal);
widget->show();
阻塞线程显示
需要阻塞线程显示的窗体类似QMessageBox的效果,例如有几个窗体需要依次显示,必须先将本窗体关闭后才能继续显示下一个。要实现阻塞线程的显示,需要使用QDialog封装显示,并调用exec()
方法。使用方法与作为内嵌控件显示类似,具体示例如下:
QWidget *widget = pluginManager->GetPanel();
QDialog *dialog = new QDialog();
QVBoxLayout *vBoxLayout = new QVBoxLayout();
vBoxLayout->addWidget(widget);
dialog->setLayout(vBoxLayout);
dialog->exec();