从不同类添加的小部件内的 PyQt5 停止计时器
Posted
技术标签:
【中文标题】从不同类添加的小部件内的 PyQt5 停止计时器【英文标题】:PyQt5 stop timer inside a widget that was added from a different class 【发布时间】:2020-01-25 12:53:04 【问题描述】:我想在多个窗口的顶部显示当前日期和时间,所以我创建了这个顶部小部件的一个类。它可以工作,但是当我切换到另一个窗口时,计时器也会继续在前一个窗口上运行。如何在切换窗口之前停止计时器,也许让相同的实例在新窗口上运行?
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】:我不认为 QTimer 的执行会减慢应用程序的速度。
但我仍然会向您展示如何从另一个窗口阻止它。为此,您必须访问该对象,因此您必须成为该类的成员,然后当您更改窗口时,您可以使用 QTimer 的 stop 方法停止它。
class Window1(QMainWindow):
# ...
def initUI(self):
# ...
layoutTop = QHBoxLayout(widgetTop)
self.topbar = TopBar()
layoutTop.addWidget(self.topbar)
layoutTop.setContentsMargins(0, 0, 0, 0)
# ...
def goToWindow2(self):
global CurrentWindow
self.topbar.timer.stop()
CurrentWindow = Window2()
self.close()
class Window2(QMainWindow):
# ...
def initUI(self):
# ...
layoutTop = QHBoxLayout(widgetTop)
self.topbar = TopBar()
layoutTop.addWidget(self.topbar)
layoutTop.setContentsMargins(0, 0, 0, 0)
# ...
def goToWindow1(self):
global CurrentWindow
self.topbar.timer.stop()
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_())
【讨论】:
第二个选项对我来说似乎是最佳解决方案,谢谢!我有一个连接到计时器的耗时函数,这会减慢应用程序的速度,但我用 QThread 替换了它,它也应该只有一个带有第二个选项的实例。 @SmileXS4 所以问题不是 QTimer 而是耗时的函数,你不这么认为吗?在您的问题中,没有任何内容。如果你有一个耗时的任务,那么你不应该在主线程中执行它,而是在辅助线程中执行它。如果您需要帮助,您必须提供真实的minimal reproducible example,否则您会混淆社区。span> 抱歉,我编辑了这个问题,因为我需要帮助来一次只运行一个计时器,而不是更快地运行应用程序。以上是关于从不同类添加的小部件内的 PyQt5 停止计时器的主要内容,如果未能解决你的问题,请参考以下文章
将 MouseDoubleClickEvent 添加到 PyQt5 中的 for 循环中制作的小部件 [重复]
如何在不影响 Pyqt5 中的小部件的情况下将背景图像添加到主窗口