用于类似对话框实现的 Qt5 和 Pattern
Qt5 and Pattern for similar dialogs implementation
您认为在不重复代码的情况下在 Qt5 中实现类似对话框的最佳方式是什么?
这就是问题所在:有两个 "slightly different" 数据结构,有许多公共部分,实现两个 "slightly different" QDialog 来处理用户交互。
我们有两种结构:
class DataA {
public:
int one, two, three;
bool x,y;
SubdataA subA;
}
class DataB {
public:
int one, two, three;
bool x,y;
SubdataB subB;
}
SubdataX是我们在GUI中需要处理的其他一些结构化数据。两个QDialog对公共字段的处理应该是一样的,而SubdataX则必须由特定的部分来处理。代码还应该对数据结构进行一些操作,并提供输出文件。这部分很简单。
我的问题是,实现这个的最佳策略是什么? objective 是为了拥有优雅的代码,应该很容易维护,并且尽可能具有最高的可读性。框架是Qt,所以解决方案应该在UI文件中使用qdialog布局针对Qt进行定制,因为gui布局太复杂而无法通过代码设计。
谢谢。
我不确定 "difficult to manage the ancestor class" 是什么意思。我想我明白你想要一个多态输入来确定对话框的布局。这个假设正确吗?
例如,给定以下 类,您可以使用动态转换来影响对话框的行为。
class IData {
public;
int one, two, three;
bool x, y;
};
class DataA : public IData {
public:
// more data in here
};
class DataB : public IData {
public:
// more unique data in here
}
现在,假设您已经编写了一个带有函数签名的对话框
void configureDialog(IData *data) {
DataA *dataA = dynamic_cast<DataA*>(data);
if (dataA) {
// configure what parts of the QDialog to see here
}
DataB *dataB = dynamic_cast<DataB*>(data);
if (dataB) {
// configure other parts of the QDialog you want to see
}
}
这将允许单个 QDialog
框的多态配置。
正如 Tyler Jandreau 所说,一种可能的解决方案是使用多态性。
但这需要仔细规划体系结构和 class 继承,因为要避免使用向下转换和大量无法维护的 switch() 情况,您还需要在 GUI classes.
根据 View/Model 体系结构的要求,数据 classes 将被 control/Gui classes 模仿。
数据 classes 将使用祖先、抽象 class CommonData
实现,其中包括公共 "fields" 和两个(或更多)具体数据 classes 通过继承从 CommonData
派生。我的第一个想法是改用组合,但这会在实现 gui 时带来其他问题。
所以DataA
和DataB
是从CommonData
推导出来的。
在 Gui 方面,结构类似,但是由于缺少对 Qt 的 uic
生成的 UI 形式 classes 的继承支持,我们无法使用继承。我的第一个猜测是使用模板元编程,并将祖先 class 作为模板 class 实现,但尽管它在 C++ 端有效,moc
拒绝解析 class并在标记为 class 的 Q_OBJECT
是模板时生成 moc_X
文件。
所以我们将混合使用继承和组合。
这是架构:"container" GUI class (ContainerDialog
) 为 CommonData
[实现了 GUI class; PluggableInterface
抽象 class 将定义一组操作(我们将在下面看到);从后者派生的一组具体 classes 将为其余 classes 实现 GUI 逻辑。
因此 ContainerDialog
将 ContainerDialog.ui
表单加载为 "standard" QDialog,并使用 CommonData
管理所有界面。他的构造函数,或者说一个setter会收到一个CommonData
指针,记住CommonData
是抽象的,不能实例化。
特定字段通过 ContainerDialog gui 中 "plugged" 的特定图形组件进行管理。例如,在 PluggableInterface
中定义的方法将在 ContainerDialog gui 中插入 QWidget 派生组件。涉及的class例如ComponentA1
、ComponentA2
、ComponentB
等...
抽象接口 PluggableInterface
和 UI 组件的使用将阻止 ContainerDialog
知道正在使用哪种具体 class,以及所有实例化特定 classes 的必要代码可以使用一些创建模式(抽象工厂、原型等...)
您认为在不重复代码的情况下在 Qt5 中实现类似对话框的最佳方式是什么?
这就是问题所在:有两个 "slightly different" 数据结构,有许多公共部分,实现两个 "slightly different" QDialog 来处理用户交互。
我们有两种结构:
class DataA {
public:
int one, two, three;
bool x,y;
SubdataA subA;
}
class DataB {
public:
int one, two, three;
bool x,y;
SubdataB subB;
}
SubdataX是我们在GUI中需要处理的其他一些结构化数据。两个QDialog对公共字段的处理应该是一样的,而SubdataX则必须由特定的部分来处理。代码还应该对数据结构进行一些操作,并提供输出文件。这部分很简单。
我的问题是,实现这个的最佳策略是什么? objective 是为了拥有优雅的代码,应该很容易维护,并且尽可能具有最高的可读性。框架是Qt,所以解决方案应该在UI文件中使用qdialog布局针对Qt进行定制,因为gui布局太复杂而无法通过代码设计。
谢谢。
我不确定 "difficult to manage the ancestor class" 是什么意思。我想我明白你想要一个多态输入来确定对话框的布局。这个假设正确吗?
例如,给定以下 类,您可以使用动态转换来影响对话框的行为。
class IData {
public;
int one, two, three;
bool x, y;
};
class DataA : public IData {
public:
// more data in here
};
class DataB : public IData {
public:
// more unique data in here
}
现在,假设您已经编写了一个带有函数签名的对话框
void configureDialog(IData *data) {
DataA *dataA = dynamic_cast<DataA*>(data);
if (dataA) {
// configure what parts of the QDialog to see here
}
DataB *dataB = dynamic_cast<DataB*>(data);
if (dataB) {
// configure other parts of the QDialog you want to see
}
}
这将允许单个 QDialog
框的多态配置。
正如 Tyler Jandreau 所说,一种可能的解决方案是使用多态性。
但这需要仔细规划体系结构和 class 继承,因为要避免使用向下转换和大量无法维护的 switch() 情况,您还需要在 GUI classes.
根据 View/Model 体系结构的要求,数据 classes 将被 control/Gui classes 模仿。
数据 classes 将使用祖先、抽象 class CommonData
实现,其中包括公共 "fields" 和两个(或更多)具体数据 classes 通过继承从 CommonData
派生。我的第一个想法是改用组合,但这会在实现 gui 时带来其他问题。
所以DataA
和DataB
是从CommonData
推导出来的。
在 Gui 方面,结构类似,但是由于缺少对 Qt 的 uic
生成的 UI 形式 classes 的继承支持,我们无法使用继承。我的第一个猜测是使用模板元编程,并将祖先 class 作为模板 class 实现,但尽管它在 C++ 端有效,moc
拒绝解析 class并在标记为 class 的 Q_OBJECT
是模板时生成 moc_X
文件。
所以我们将混合使用继承和组合。
这是架构:"container" GUI class (ContainerDialog
) 为 CommonData
[实现了 GUI class; PluggableInterface
抽象 class 将定义一组操作(我们将在下面看到);从后者派生的一组具体 classes 将为其余 classes 实现 GUI 逻辑。
因此 ContainerDialog
将 ContainerDialog.ui
表单加载为 "standard" QDialog,并使用 CommonData
管理所有界面。他的构造函数,或者说一个setter会收到一个CommonData
指针,记住CommonData
是抽象的,不能实例化。
特定字段通过 ContainerDialog gui 中 "plugged" 的特定图形组件进行管理。例如,在 PluggableInterface
中定义的方法将在 ContainerDialog gui 中插入 QWidget 派生组件。涉及的class例如ComponentA1
、ComponentA2
、ComponentB
等...
抽象接口 PluggableInterface
和 UI 组件的使用将阻止 ContainerDialog
知道正在使用哪种具体 class,以及所有实例化特定 classes 的必要代码可以使用一些创建模式(抽象工厂、原型等...)