如何在pyqt GUI编程中组织类

4

我使用qt designer和pyqt构建了一个主窗口GUI。随着程序变得更加复杂,仅使用一个类可能会导致要管理的方法和属性过多。我想应该构建新的类来使事情更易于管理。

我的第一个问题是,我如何知道何时为我的应用程序添加新的类?是否有一般性的规则作为指导?为新的窗口/选项卡添加新类是一个好主意吗?

我的第二个问题是,如果我为我的应用程序添加了新类,我的新类如何访问我在Qt Designer中设计的Ui_MainWindow设计文件?下面是我的主窗口的示例代码。它是一个简单的时钟,显示当前时间。假设我想为时钟显示本身创建一个类,如何有效地使用OOP重写代码?

from PyQt4 import QtGui
from myMainWindowUI import Ui_MainWindow

class MyMainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        super(MyMainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.Time)
        self.timer.timeout.connect(self.Date)
        self.timer.start(1000)
        self.lcdNumber_time.setDigitCount(8)
        self.lcdNumber_time.display(strftime("%H"+":"+"%M"+":"+"%S"))
        self.label_dynamic_date.setText(strftime("%Y"+" "+"%B"+" "+"%d"+", "+"%A"))

def Time(self):
    self.lcdNumber_time.display(strftime("%H"+":"+"%M"+":"+"%S"))
def Date(self):
    self.label_dynamic_date.setText(strftime("%Y"+" "+"%B"+" "+"%d"+", "+"%A"))

app = QtGui.QApplication(sys.argv)  # A new instance of QApplication
form = MyMainWindow()                 
form.show()                         
app.exec_()

在我回答之前,你能否更新一下你的问题并提供一个示例,说明你希望从另一个类中访问哪些内容?我想确保我给出一个具体的答案。 - jdi
感谢您的回答@jdi。我已经添加了一个示例代码,以展示我想要实现的内容。 - dnth
我已经更新了我的答案,提到了自定义信号。 - jdi
1个回答

7
一般而言,这并不一定是一个Qt特有的问题。这也不是一个特定于Python的问题。您可以将此问题扩展到任何支持基于类的编程的语言,甚至是任何具有函数的语言。
当您想要封装行为时,编写一个类是有意义的。一个类通常应该提供单一目的,并公开一个接口,以允许类的用户与您设计的行为进行交互。一旦您拥有了这个单一目的的类,您现在拥有可重用的行为。您可以将部分推理应用于函数上,在其中您说给定的函数有一个特定的目的,一旦您设计它执行一位行为,现在您就有了一个可重用的函数。

将这个应用到Qt中,当代码逻辑不再简单时,将代码移动到自己的类中是有意义的。例如,您首先从主窗口创建和显示QMessageBox。但是,在某些情况下,您需要收集更多类型的信息,甚至在构造对话框时传递一些初始信息。虽然您可以根据需要在主窗口中即时构建它,但最好将其移动到自己的对话框类中,并具有自己的私有逻辑以进行构建。然后,您只需按需要实例化一个对象,将预期参数传递给其构造函数。现在,您的主窗口不再需要关注构建特殊对话框。

另外一个要点(从你的问题中并不完全清晰)是Qt Designer UI文件代表一个单独的类。预期将应用此UI定义到代码中的单个类。如果ClassA(UI_mainWindow)ClassB存在,而ClassB可以访问ClassA的成员或知道关于ClassA的内部实现的任何信息,则设计会很差。回到我们的 "关注点分离" 的主题,ClassB 应该有自己的目的和接口,并被ClassA(UI_mainWindow)用于实现该目的。您不希望ClassB 知道关于主窗口的任何信息或能够执行超出其设计目的的操作。
假设您的计时器示例实际上比您展示的更为简单。如果将其移动到另一个类中,则应依赖于自定义信号来向其他类(如主窗口)传达意图。或者,您可以将每个lcd和label小部件移动到其自己的自定义类中,并具有使它们自包含的定时器逻辑。无论哪种方式,信号/槽允许自定义小部件彼此连接而无需了解其他小部件的任何内容。
总之,在Qt中构建任何非平凡的UI元素时(当它需要很多代码行或需要一堆SLOT函数和内部逻辑的布线时),创建单独的类会很好。这将使您避免重复逻辑,并允许您拥有可重用的代码。这也将使您的主窗口更小且更易于调试,因为您可以在脑海中保持较小的模型以了解主窗口正在执行的操作。如果尝试使UI元素尽可能专注于单一目的并且通用化,那么最终将拥有许多可重用的类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接