【问题标题】:Writing modular codes in python用python编写模块化代码
【发布时间】:2015-10-12 11:26:19
【问题描述】:

您好,我有一个简单的 GUI,如下所示,带有 2 个按钮。我编写了一个方法,一旦单击按钮就会更改按钮上的文本。我想使该方法模块化和通用,以便将该方法应用于任何按钮而无需重写。在下面的示例中,如何在不为其定义新方法的情况下将 printWow() 方法应用于按钮 2?

import sys
from PyQt4.Qt import *

class MainWindow(QMainWindow):
    def __init__(self, *args):
        QMainWindow.__init__(self, *args)
        self.cw = QWidget(self)
        self.setCentralWidget(self.cw)
        self.btn1 = QPushButton("Click me", self.cw)
        self.btn1.setGeometry(QRect(50, 50, 100, 30))
        self.btn1.clicked.connect(self.printWow)

        self.btn2 = QPushButton("Click me", self.cw)
        self.btn2.setGeometry(QRect(50, 20, 100, 30))
        self.btn2.clicked.connect(self.printWow)

    def printWow(self):
        self.btn1.setText("WoW")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myapp = MainWindow()
    myapp.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python class oop pyqt modular-design


    【解决方案1】:

    基本上,使函数“更通用”意味着识别不同用例中的变体和不变量。在您的示例中,变体将是您要调用 setText() 的对象,最终是文本本身,因此您的“通用”函数看起来像:

    def printText(self, target, text="wow"):
        target.setText(text)
    

    然后,由于您无法将这些参数传递给connect()(至少让我们假设在我们的示例中是这种情况),您需要将泛型函数的引用和参数包装在一起,可以不带参数调用。这是“部分评估”的一个例子,最简单的形式只需要lambda

    class MainWindow(QMainWindow):
        def __init__(self, *args):
            QMainWindow.__init__(self, *args)
            self.cw = QWidget(self)
            self.setCentralWidget(self.cw)
            self.btn1 = QPushButton("Click me", self.cw)
            self.btn1.setGeometry(QRect(50, 50, 100, 30))
            self.btn1.clicked.connect(lambda: self.printWow(self.btn1))
    
            self.btn2 = QPushButton("Click me", self.cw)
            self.btn2.setGeometry(QRect(50, 20, 100, 30))
            self.btn2.clicked.connect(lambda: self.printText(self.btn2, "Yay!"))
    
        def printText(self, target, text="wow"):
            target.setText(text)
    

    请注意,在上面的示例中,您不会从额外的复杂性中获得太多收益 - 您也可以将所有内容都放在 lambda 中,即:

    self.btn1.clicked.connect(lambda: self.btn1.setText("Wow"))
    self.btn2.clicked.connect(lambda: self.btn2.setText("Yay !"))
    

    但我假设你有更复杂的想法......

    既然你提到了“模块化”(至少在你的标题中),“模块化”代码的真正关键不一定(或至少不仅)分解出通用代码,而且主要是很好地分割你的代码解耦的模块,每个模块都有明确和不同的职责。一个典型的例子是将 UI 代码从“域”代码中分离出来——这些代码完成了真正的工作,甚至根本不应该知道 UI 的存在......

    【讨论】:

      【解决方案2】:

      您可以使用sender() 方法确定单击了哪个按钮。

      如果在由信号激活的槽中调用,则返回指向发送信号的对象的指针;否则返回 0。该指针仅在从该对象的线程上下文调用该函数的槽执行期间有效。

      如果发送者被销毁,或者槽与发送者的信号断开,则此函数返回的指针无效。

      但文档中有一个重要警告,它会与您的帖子标题冲突:

      警告:此函数违反了面向对象的模块化原则。但是,当多个信号连接到单个插槽时,访问发送器可能会很有用。


      你可以像这样使用sender()

      def printWow(self):
          self.sender().setText("WoW")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-22
        • 2017-09-23
        • 1970-01-01
        相关资源
        最近更新 更多