是否可以在Qt设计器中使用依赖项注入(对于.ui文件)
Is it possible to use dependency injection with Qt Designer (for .ui files)?
我们正在C++(和Qt)中使用Visual Studio 2015和用于UI的Qt设计器(通过Form/.UI文件)进行开发。
我们现在需要在UI元素之间共享一些公共数据(例如,最近使用的路径等),我希望通过依赖注入(即,在构建过程中为UI提供对公共对象的引用)来实现这一点,而不是例如(ab)使用单例模式。
有人面临过(并解决过)类似的问题吗?有合理的方法吗?
更新(详细说明):
例如,我有一个自定义的FooWidget
,我希望在我的FooDialog.ui
表单文件中使用它。
// My custom Widget
class FooWidget : public QWidget {
Q_OBJECT
public:
FooWidget(QWidget* parent);
//...
}
// The FooDialog class (scaffolding created by Qt Designer)
class FooDialog : public QDialog {
Q_OBJECT
public:
FooDialog(QWidget* parent) : QDialog(parent), ui (new Ui::FooDialog()) {
ui->setupUp(this);
//...
}
private:
Ui::FooDialog* ui;
}
// The Ui::FooDialog class autogenerated(!) by Qt Designer
// I cannot (must not) change this code, as it will be regenerated every time
class Ui_FooDialog {
public:
FooWidget* widget;
void setupUi(QWidget *fooDialog) {
//...
widget = new FooWidget(fooDialog);
//...
}
}
namespace Ui { class ScannerStatus: public Ui_ScannerStatus {}; }
我想为FooWidget提供一个通用的数据对象(例如,在我的所有Ui类中共享的文本大小和颜色),但我不能在构造函数中这样做(因为自动生成的Ui_FooDialog将FooWidget
视为通用QWidget
,它只需要/接受构造函数中的QWidget* parent
-我不能提供指向共享TextColourAndSize
对象的指针或引用。
我知道我可以在FooDialog
中创建第二个ui->widget->setupTextColourAndSize(...)
步骤(在最初的ui->setupUi(this)
之后),它提供了公共数据对象,但拥有两个init()
类型的函数似乎是一种相当糟糕的代码气味(一个已经足够糟糕了)。
FooWidget
需要两个构造函数和一个依赖项的setter:
explicit FooWidget(QObject *parent = nullptr) : QWidget(parent), … {
…
}
FooWidget(Dependency *dep, QObject *parent = nullptr) : FooWidget(parent) {
setDependency(dep);
}
void setDependency(Dependency *dep) {
…
}
然后在构建小部件后设置依赖项:
FooDialog(Dependency *dep, …) … {
setupUi(this);
ui->fooWidget->setDependency(dep);
}
这可以是自动化的:父小部件可以有一个属性来保存指向依赖项的指针,子小部件可以自动找到它:
FooDialog(Dependency *, …) : … {
setProperty("dependency", dep);
setupUi(this);
}
FooWidget(QWidget *parent) : … {
auto *dep = parent() ? parent()->property("dependency").value<Dependency*>() : nullptr;
if (dep) setDependency(dep);
}
如果Dependency
是从QObject
派生而来,那么这将不需要额外的努力。否则,您需要在合适的头文件中包含以下内容:
class Dependency { … };
Q_DECLARE_METATYPE(Dependency*)
在任何情况下,都需要在Qt Designer中将fooWidget
对象提升为FooWidget
类。
好吧,根据我所看到的,您不需要"依赖注入"。问题陈述错误。
您可以直接从Qt设计器使用此自定义小部件。
- 创建
FooDialog
时,将常规小部件QWidget
放置在需要FooWidget
的位置 - 然后将这个小部件"升级"到
FooWidget
(可能需要添加一些关于该类型的简单信息)-(我很久以前就这样做了,不记得所有细节)
关于谷歌的详细说明:qt推广小工具qt设计器,你会发现很多例子如何做到这一点。
这些都是很好的解决方案,但在谈到依赖注入时,也可以选择用C++来获得一些乐趣。这根本不是一个明智的解决方案,我当然知道,但尽管如此。。。
foowidget.h
#ifndef FOOWIDGET_H
#define FOOWIDGET_H
#include <QWidget>
class Something
{
public:
QString getHello() const
{ return "Hello world!"; }
};
/***************************************************/
template<typename T>
class Injector
{
public:
QString getHello() const
{ return m_dataContainer.getHello(); }
private:
T m_dataContainer;
};
/***************************************************/
class FooWidget : public QWidget, public Injector<Something>
{
Q_OBJECT
public:
explicit FooWidget(QWidget* parent = nullptr);
protected:
virtual void mousePressEvent(QMouseEvent*) override;
};
#endif // FOOWIDGET_H
foowidget.cpp
#include "foowidget.h"
#include <QMessageBox>
FooWidget::FooWidget(QWidget *parent)
: QWidget(parent)
{ }
void FooWidget::mousePressEvent(QMouseEvent*)
{
QMessageBox::information(nullptr, "Test", getHello());
}
foodialog.h
#ifndef FOODIALOG_H
#define FOODIALOG_H
#include <QDialog>
class SomethingElse
{
public:
QString getHello() const
{ return "OMG! OMG"; }
};
#include "foowidget.h"
namespace Ui {
class FooDialog;
}
class FooDialog : public QDialog, public Injector<SomethingElse>
{
Q_OBJECT
public:
explicit FooDialog(QWidget *parent = nullptr);
~FooDialog();
protected:
void showEvent(QShowEvent *) override;
private:
QScopedPointer<Ui::FooDialog> ui;
};
#endif // FOODIALOG_H
foodialog.cpp
#include "foodialog.h"
#include "ui_foodialog.h"
#include <QMessageBox>
FooDialog::FooDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::FooDialog)
{
ui->setupUi(this);
}
FooDialog::~FooDialog()
{ }
void FooDialog::showEvent(QShowEvent *)
{
QMessageBox::information(nullptr, "Test", getHello());
}
多继承+从一些小模板代理类派生小部件既适用于自定义小部件,也适用于具有UI表单的小部件。在上面的草图中,我在FooDialog上放置了一个FooWidget(通过传播机制),并得到了两个消息框。
这个想法本身可以更好地实现,使用更智能的模板,只是试图减少样本代码,无论如何,这是一个不必要的复杂性。但从技术上讲,它可以在没有任何额外初始化的情况下工作=)
- 限定的依赖名称查找,其中包含基类的注入类名
- 如何在不诉诸依赖注入的情况下模拟遗留函数?
- 类成员和依赖项注入的对象与引用
- C++如何在派生类上进行依赖项注入
- 正确构造和销毁 Setter 依赖注入对象(可能使用 qt)
- 依赖注入:依赖关系需求字段/成员
- 现代编译器是否可以在使用依赖关系注入时取消虚拟化函数调用
- 模板或链接接缝依赖注入有哪些替代方案来测试非虚拟方法?
- 类型擦除代码的依赖注入单元测试
- 包装类设计和依赖注入
- 在进行依赖注入时公开私有方法
- 是否可以在Qt设计器中使用依赖项注入(对于.ui文件)
- 有趣的C++依赖注入方案
- 使用X3对解析器的依赖注入
- 我如何使用Gmock进行依赖注入
- 重构Singleton/Globals以使用依赖注入进行单元测试
- 依赖关系注入和事件处理
- 依赖注入/继承设计模式的构造函数参数太多
- 依赖项注入在C++中有用吗
- 用水果注入C++依赖