Таймер остановки PyQt5 внутри виджета, который был добавлен из другого класса - PullRequest
1 голос
/ 25 января 2020

Я хотел бы отображать текущую дату и время в верхней части нескольких windows, поэтому я создал класс этого верхнего виджета. Это работает, однако, когда я переключаюсь в другое окно, таймер продолжает работать и в предыдущем окне. Как я могу остановить таймер прямо перед переключением окна, возможно, сохранить тот же экземпляр в новом окне?

from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QWidget
import sys
from datetime import datetime

CurrentWindow = None

class TopBar(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.labelTime = QtWidgets.QLabel(self)
        self.labelTime.setStyleSheet("background-color: rgba(0, 0, 0, 0); color: white")

        background = QtWidgets.QWidget(self)
        background.setStyleSheet("background-color: rgba(0, 191, 255, 0.6)")
        background.setGeometry(0, 0, 480, 30)

        hbox = QHBoxLayout(background)
        hbox.setContentsMargins(10, 0, 10, 0)
        hbox.addWidget(self.labelTime, alignment=QtCore.Qt.AlignRight)

        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.displayTime)
        self.timer.start()

        self.displayTime()


    def displayTime(self):
        print(self.parent())
        self.labelTime.setText(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))


class Window1(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.resize(480, 320)

        self.centralwidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralwidget)

        widgetTop = QtWidgets.QWidget(self.centralwidget)
        widgetTop.setGeometry(0, 0, 480, 30)

        layoutTop = QHBoxLayout(widgetTop)
        layoutTop.addWidget(TopBar())
        layoutTop.setContentsMargins(0, 0, 0, 0)

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setText('Go to Window2')
        self.pushButton.clicked.connect(self.goToWindow2)

        layoutCenter = QHBoxLayout(self.centralwidget)
        layoutCenter.addWidget(self.pushButton, alignment=QtCore.Qt.AlignCenter)

        self.show()


    def goToWindow2(self):
        global CurrentWindow
        CurrentWindow = Window2()
        self.close()


class Window2(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.resize(480, 320)

        self.centralwidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralwidget)

        widgetTop = QtWidgets.QWidget(self.centralwidget)
        widgetTop.setGeometry(0, 0, 480, 30)

        layoutTop = QHBoxLayout(widgetTop)
        layoutTop.addWidget(TopBar())
        layoutTop.setContentsMargins(0, 0, 0, 0)

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setText('Go to Window1')
        self.pushButton.clicked.connect(self.goToWindow1)

        layoutCenter = QHBoxLayout(self.centralwidget)
        layoutCenter.addWidget(self.pushButton, alignment=QtCore.Qt.AlignCenter)

        self.show()


    def goToWindow1(self):
        global CurrentWindow
        CurrentWindow = Window1()
        self.close()



if __name__=='__main__':
    app = QApplication(sys.argv)
    ex = Window1()
    sys.exit(app.exec_())

1 Ответ

2 голосов
/ 25 января 2020

Не думаю, что выполнение QTimer замедляет работу приложения.

Но я все равно покажу вам, как остановить его из другого окна. Чтобы сделать это, вы должны получить доступ к объекту, чтобы стать членом класса, а затем, когда вы изменяете окно, вы останавливаете его с помощью метода stop QTimer.

class Window1(QMainWindow):
    # ...

    def initUI(self):
        # ...
        layoutTop = QHBoxLayout(widgetTop)
        <b>self.topbar = TopBar()
        layoutTop.addWidget(self.topbar)</b>
        layoutTop.setContentsMargins(0, 0, 0, 0)
        # ...

    def goToWindow2(self):
        global CurrentWindow
        <b>self.topbar.timer.stop()</b>
        CurrentWindow = Window2()
        self.close()


class Window2(QMainWindow):
    # ...

    def initUI(self):
        # ...
        layoutTop = QHBoxLayout(widgetTop)
        <b>self.topbar = TopBar()
        layoutTop.addWidget(self.topbar)</b>
        layoutTop.setContentsMargins(0, 0, 0, 0)
        # ...

    def goToWindow1(self):
        global CurrentWindow
        <b>self.topbar.timer.stop()</b>
        CurrentWindow = Window1()
        self.close()

Если вы все еще считаете, что причина ошибки состоит в том, чтобы иметь несколько QTimer, тогда в следующем коде будет только один TopBar, и они изменят виджет с помощью QStackedWidget

from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QWidget
import sys
from datetime import datetime


class TopBar(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setAttribute(QtCore.Qt.WA_StyledBackground)
        self.labelTime = QtWidgets.QLabel()
        self.labelTime.setStyleSheet("background-color: rgba(0, 0, 0, 0); color: white")

        self.setStyleSheet("background-color: rgba(0, 191, 255, 0.6)")
        self.setFixedHeight(30)

        hbox = QHBoxLayout(self)
        hbox.setContentsMargins(10, 0, 10, 0)
        hbox.addWidget(self.labelTime, alignment=QtCore.Qt.AlignRight)

        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.displayTime)
        self.timer.start()

        self.displayTime()

    def displayTime(self):
        self.labelTime.setText(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))


class Window(QWidget):
    changeWindow = QtCore.pyqtSignal(int)

    def changeTo(self, index):
        def callback():
            self.changeWindow.emit(index)

        return callback


class Window1(Window):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.pushButton = QtWidgets.QPushButton()
        self.pushButton.setText("Go to Window2")
        self.pushButton.clicked.connect(self.changeTo(1))

        layoutCenter = QHBoxLayout(self)
        layoutCenter.addWidget(self.pushButton, alignment=QtCore.Qt.AlignCenter)


class Window2(Window):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.pushButton = QtWidgets.QPushButton()
        self.pushButton.setText("Go to Window1")
        self.pushButton.clicked.connect(self.changeTo(0))

        layoutCenter = QHBoxLayout(self)
        layoutCenter.addWidget(self.pushButton, alignment=QtCore.Qt.AlignCenter)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.initUI()

    def initUI(self):
        self.resize(480, 320)

        self.centralwidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralwidget)

        self.topbar = TopBar()
        lay = QtWidgets.QVBoxLayout(self.centralwidget)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(self.topbar)

        stacked_widget = QtWidgets.QStackedWidget()
        lay.addWidget(stacked_widget)

        for w in (Window1(), Window2()):
            stacked_widget.addWidget(w)
            if isinstance(w, Window):
                w.changeWindow.connect(stacked_widget.setCurrentIndex)


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