逻辑和UI分离

Posted

技术标签:

【中文标题】逻辑和UI分离【英文标题】:Separation of logic and UI 【发布时间】:2011-08-13 14:56:24 【问题描述】:

我正在用 Qt 开发一个 GUI 应用程序。

这是我的第一个 GUI 应用程序,我不是很有经验,仍然需要与 C++ 和 Qt 框架的一些更高级的方面搏斗。

该应用程序非常简单,具有一个主窗口和一些对话框,用户可以在其中配置设置并按下按钮,然后程序执行(相当复杂的)计算,并在 UI 上的某处给出结果。

现在,我遇到了问题。我把我所有的计算数据(它是静态的并且从资源中加载)和逻辑放到一个单独的类中。我创建了这个类和 UI 类的一个实例。现在,问题是如何从 UI 类访问数据/逻辑类的成员?假设 Logic 类中有一个 QStringList,我希望某个对话框访问这个列表并将其呈现给用户,而不在内存中制作它的任何副本?

我知道这可能是一个非常基本的 C++ 问题(Qt 甚至不相关),但不是每个人都是编程向导。感谢您的任何提示或帮助!

【问题讨论】:

【参考方案1】:

有几种方法可以做到这一点,所以你的问题是有效的。

    您的 GUI 类可以派生自您的逻辑类。不是典型的方法,但这取决于您的应用程序的设计方式。一个主要缺点是,如果您不想在逻辑类中涉及锁定机制,则 GUI 必须与逻辑保持在同一线程中。通常你希望两个对象在不同的​​线程中运行,这样繁重的计算就不会冻结 GUI(参见 Qt 的QObject thread affinity)。

    您的 GUI 类可以保存指向您的逻辑类的指针和/或反之亦然。如果您的逻辑类在 GUI 类之前存在并且仍然存在,它也可能是方便的参考。然后您可以将引用传递给 GUI 类的构造函数,而无需测试指针是否有效。

    您的 GUI 类可以通过 getter/setter 或直接访问数据成员,如果您想将它们公开或简单地将您的 GUI 类定义为 Logic 类的 friend 类。即使您使用 getter,它们也可以返回 const 引用,因此不涉及复制。像 QStringList 这样的 Qt 类也有自己的引用计数,避免复制的写时复制机制。

    您的 GUI 类可以发出信号,而 Logic 类可以接收它们。请参阅 Qt 信号/槽机制。对于像“开始计算”按钮这样的事件非常好。信号有两个优点:(a)它们可以跨线程,但是如果接收器不是主循环,它会变得有点棘手; (b) 对象不必互相看到(没有指针传递),您可以将信号连接到程序中您同时看到两个对象的任何位置的槽。

通常您将混合使用 2 和 3:使用 getter 从呈现给用户的 Logic 类中读取数据。使用信号来激发动作或操作数据(用户做出选择,逻辑类必须做出反应)。

【讨论】:

您的综合回答非常非常有帮助!现在我对这种分离有了更好的理解。谢谢! 谢谢!其中有没有“最好的”? 一般我会建议使用Qt信号/槽系统。然而,原因是无论如何我都会将 Qt 用于 GUI。【参考方案2】:

有一种编程模型叫做MVC(模型-视图-控制)

对于简单的情况,只需模型 - 视图就足够了。 Model代表数据,View代表UI。

模型类公开了一些接口设置/获取数据。 Model类通常不知道View类,但通常可以在数据发生变化时通知View类(这可以通过Qt中的信号/槽来完成)。

View 类持有指向 Model 类的指针,并使用 Model 类提供的接口来操作数据。

【讨论】:

【参考方案3】:

也许我在这里遗漏了一些东西,但只需通过 setter 将您的数据类注入 UI 类,并将数据类的方法公开。您只需要传递数据类的指针即可避免任何应对开销。

【讨论】:

以上是关于逻辑和UI分离的主要内容,如果未能解决你的问题,请参考以下文章

UI与数据分离 与 UI的演进

PyQt5 - 将逻辑与 ui 分离导致功能无法正常工作

PyQt5中编程与界面设计分离的两种方式(UI逻辑分离)

PyQt5系列教程如何让界面和逻辑分离

第三篇 -- 界面与逻辑分离的设计方法(多继承方法和单继承方法)

tkinter的GUI设计:界面与逻辑分离