我的問題是如何在使用Qt插件時進行適當的對象/資源管理。默認的RAII似乎並不適用於Qt。使用Qt插件進行Qt對象管理
在我們的應用程序中,我們使用在運行時動態加載的模塊(Qt插件)。當被加載的插件可以初始化自己並且作爲這個初始化階段的一部分時,他們可以將他們自己的小部件添加到應用程序中 - 轉到工具欄 - 轉到側面板 - 等 添加到主窗口的窗口小部件的所有權也已轉移。
這一切都很好,但現在我們的應用程序變得更加複雜了,我們還需要注意關閉階段。簡單地卸載模塊將使我們陷入各種麻煩。不存在的對象或在對象仍處於活動狀態時卸載的類型。
要有可靠的關閉,似乎唯一正確的方法是進行反向初始化。這也意味着向主窗口添加小部件的每個模塊都必須刪除它們。已經試圖用第一個小工具做到這一點讓我陷入困境。
模塊A使用MainWindow註冊W部件。最好我想要返回一個範圍對象,當超出範圍時刪除和刪除小部件。然而,已經看起來給定的小部件W不能從工具欄簡單地刪除它,因爲它與動作一起工作(並且刪除動作不會刪除小部件!請參閱下面的示例)。
最後總結一下,在我看來,Qt是以這樣一種方式獲得的,它獲得了所有權的所有權,您必須依靠Qt來刪除它。這不適用於模塊。我正在尋找解決方案/最佳做法。
編輯:
我添加了一個示例,其中一個模塊將一個自定義小部件添加到MainWindow的工具欄中。我的目標是,由於之前所述的原因,該模塊負責刪除小部件。例子是讓問題更具體。它代表了通用問題--qt對象的所有權 - 將這種模式與插件結合使用。
例如:
executable.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;
};
module.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;
};
謝謝,但我不知道我得到如何解決我的問題。我在我的開場白中增加了一個例子,使其更加具體。除非我誤解了,否則你會建議讓小部件擁有作爲所有者的插件對象,但是如果我理解正確,那麼這種方法不起作用,因爲MainWindow會竊取此所有權。 –