PyQt5 - 封装/使组件可重用 - 示例:QTimer/QLabel 在父 class 之外实现

PyQt5 - encapsulate / make a component reusable - example: QTimer/QLabel implementation outside of parent class

我在我的几个 PyQt5 应用程序中实现了一个显示当前时间的标签。这是一个 MRE:

import sys 
import logging

from PyQt5 import QtWidgets, QtCore, QtGui

__log__ = logging.getLogger()


class App(QtWidgets.QApplication):
    
    def __init__(self, sys_argv):
        super(App, self).__init__(sys_argv)
        self.main_view = MainView()
        self.main_view.show()


class MainView(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setObjectName("MreUi")
        self.resize(300, 100)
        self.setWindowTitle('MreUi')
        self.label = QtWidgets.QLabel()
        self.setCentralWidget(self.label)
        config_clock(self.label)
        self.start_clocks()
        
    def start_clocks(self):
        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.show_time)  
        timer.start(1000)
        
    def show_time(self):
        current_time = QtCore.QTime.currentTime()
        clock_label_time = current_time.toString('hh:mm:ss')
        self.label.setText(clock_label_time)


def config_clock(label):
    label.setAlignment(QtCore.Qt.AlignCenter)
    font = QtGui.QFont('Arial', 24, QtGui.QFont.Bold)
    label.setFont(font)
        
        
if __name__ == '__main__':
    logging.basicConfig()
    app = App(sys.argv)
    try:
        sys.exit(app.exec_())
    except Exception as e:
        __log__.error('%s', e)

当我在我的几个 PyQt 应用程序中实现了一个类似的时钟时,我认为将它实现为一个组件/封装它会很好。首先,我想到通过从任何 QWidget 调用一个 config_clock 函数来做到这一点,并让该函数完成~所有为指定标签实现时钟的工作。这将避免在多个应用程序中重复使用 MainView 的 writing/calling start_clocks 和 show_time 实例方法。但是当我开始编写代码时...

# from inside my QWidget:
config_clock(self.label)

# this function would live outisde the class, thus reusable by diff Qt apps:
def config_clock(label):
   # start the clock
   # set default font, etc for label
   # instantiate QtCore.QTimer
   # # but that's when I realized I've always passed self to QtCore.QTimer and that maybe encapsulating this isn't as trivial as I thought.

我是否应该创建我自己的某种 ClockLabel() 对象,它被传递给 QtWidget 的标签并且也可以是每个可能需要它的 QtWidget 的实例属性?这对我来说有点笨重。但肯定有办法在 PyQt 中制作 'reusable component',我只是不知道如何...

我也不确定如果我将 MainView(QtWidgets.QMainWindow) 作为参数传递给 ClockLabel() class 我写了一个 config_clock 函数,其签名可能如下所示:

def config_clock(label, parent_qtwidget):
# also feels clunky and not sure if parent would be the right term

谢谢

对于 QtWidgets,通过继承来专门化小部件是正常的。以下是您可以如何重新排列代码以生成可重用小部件的示例:

class ClockLabel(QtWidgets.QLabel):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setAlignment(QtCore.Qt.AlignCenter)
        font = QtGui.QFont('Arial', 24, QtGui.QFont.Bold)
        self.setFont(font)

        self._timer = QtCore.QTimer(self)
        self._timer.timeout.connect(self._show_time)

    def start(self):
        self._timer.start(1000)

    def stop(self):
        self._timer.stop()

    def _show_time(self):
        current_time = QtCore.QTime.currentTime()
        clock_label_time = current_time.toString('hh:mm:ss')
        self.setText(clock_label_time)