使用Qt插件管理Qt对象
Qt object management with Qt Plugins
我的问题是在使用Qt插件时如何进行正确的对象/资源管理。默认RAII似乎无法很好地与Qt配合使用。
在我们的应用程序中,我们使用在运行时动态加载的模块(Qt插件)。当加载的插件可以初始化自己时,作为初始化阶段的一部分,他们可以将自己的小部件添加到应用程序中。-到工具栏-到侧板-等等。添加到主窗口的小工具的所有权也会转移。
这一切都很好,但现在我们的应用程序变得越来越复杂,我们也需要注意关闭阶段。简单地卸载模块就会给我们带来各种各样的麻烦。不存在的对象或在其对象仍处于活动状态时卸载的类型。
要想可靠地关闭,似乎唯一正确的方法就是进行反向初始化。这也意味着,每个向主窗口添加小部件的模块也必须删除它们。已经尝试用第一个小部件来做这件事了,这让我陷入了麻烦。
模块A向主窗口注册小部件W。最好我想返回一个作用域对象,在超出作用域时删除和删除小部件。然而,给定的小部件W似乎已经无法简单地从工具栏中删除它,因为它与操作一起工作(删除操作并不会删除小部件!参见下面的示例)。
最后,在我看来,Qt是以这样一种方式制作的,它获得了所有东西的所有权,你必须依靠Qt来删除它。这对模块来说不太好。我在这里寻找解决方案/最佳实践。
编辑:
我添加了一个示例,其中一个模块将一个自定义小部件添加到MainWindow的工具栏中。我的目标是,模块负责删除小部件的时间,原因如上所述。这个例子是为了使问题更加具体。它代表了将这种模式与插件结合使用的一般问题——qt对象的所有权。
示例:
可执行.cpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) {
ui->setupUi(this);
LoadPlugin();
}
void LoadPlugin() {
m_plugin = new QPluginLoader("module.dll");
m_plugin->load();
IModule* moduleInstance = qobject_cast<IModule*>(m_plugin->instance());
moduleInstance->Initialize(this);
}
void AddToolbarSection(QWidget* widget) {
/** ownership is transferred here to Qt */
mainToolBar->insertWidget(pWidget);
}
void RemoveToolbarSection(){
/** How to get the widget deleted? */
}
/** this is called before the destructor */
void UnloadPlugin() {
moduleInstance->Shutdown();
m_plugin->unload();
}
~MainWindow() {
/** deletion of toolbar sections must already been done here
as the modules are already unloaded. Otherwise access violations occur
because specific type information is not accessible anymore.
*/
}
private:
Ui::MainWindow *ui;
QPluginLoader* m_plugin;
IModule* m_moduleInstance;
};
模块.cpp
class EXPORT_MODULE IModule : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID IModuleIID)
Q_INTERFACES(IModule)
public:
IModule() {
}
void Initialize(QMainWindow* window) {
/** QMyToolbarSectionWidget is a custom widget defined in this module (module.dll)
it has a specific destructor and triggers all kinds application
specific cleanup */
m_toolbarSection = new QMyToolbarSectionWidget();
window->AddToolbarSection(m_toolbarSection);
}
void Shutdown() {
window->RemoveToolbarSection(m_toolbarSection);
}
private:
QWidget* m_toolbarSection;
};
这有点难以回答,因为它取决于您的体系结构。
一般来说,Qt的清理思想与父指针有关。即
QObject *root;
QObject *leaf = new QObject();
leaf->setParent(root);
root->deleteLater();
QPluginLoader甚至会在卸载时清除你的根组件,所以理论上,插件下面的任何树都会被清除。只需确保从根返回的所有内容都是根的QObject。如果它不是QObject,请将其包装在QObject中。
class MyExtension : public QWidget {
QAction *myAction;
MyExtension() : QWidget() {
myAction = new QAction(this);
}
QAction *getAction() {
return myAction
}
}
根据你的问题,我知道你可能也在这样工作:
class MyExtension : public QObject {
MyWindow * myWindow;
QAction * myAction;
MyExtension() : QObject() {
myWindow = new MyWindow(this);
myAction = new QAction(this);
}
void addToMainThing(TheMainThing *tmt) {
tmt->addWidget(myAction);
}
}
同样的事情。只需始终确保您的QObject是插件根目录的父对象。
在Qt论坛上交叉发布这个问题得到了以下答案。即使Qt拥有添加到Ui的QWidgets/QObjects的所有权,仍然可以从客户端删除它们。Qts资源管理系统的构建方式是,它将知道QObject何时被删除,并通过更新UI和删除对它的内部引用来处理此删除。有关更多详细信息,请参阅链接。
- 通过插槽和信号在不同线程中的两个qt对象之间进行通信
- 如何注册Qt C++对象以在QML中使用它
- Qt对象所有权内存泄漏
- 以延长构造函数外部 QT 对象的生存期
- 我有一个 Qt 对象的 2d 数组,我已经用值播种了这些对象。如何访问数组中特定对象的值并更改它们?
- Qt对象如果使用'this'创建(更新)需要删除或自动删除?
- 在 cmake 中链接 Qt 对象
- 将流运算符添加到 Qt 对象
- 在 QT 对象类中声明 PCL 点云
- QT对象::连接:没有此类插槽信号到线程插槽
- 如何在调试期间查看Qt对象QByteArray的内容
- Qt对象删除导致崩溃
- 如何从线程的结果返回Qt对象(Qtfutur)
- QtWebkit javascript bridge,无法访问 Qt 对象方法
- 将 Qt 对象与 std::shared_ptr 一起使用
- 带有 Qt 对象的 Cmake 库
- 向QML公开复杂的Qt对象C++
- 从另一个 std::thread 调用 Qt 对象方法
- Qt 对象实例化查询
- C++中的静态成员Qt对象