这可以很好地工作,并通过调用update_label_colors函数来更新标签:
timer = QtCore.QTimer()
# connect the timer to the update function
timer.timeout.connect(update_label_colors)
# start the timer with an interval of 1000 milliseconds (1 second)
timer.start(1000)
但在这之后叫做:
def stop_build_timer():
...
timer.stop()
...
然后这个
def start_build_timer():
...
timer.timeout.connect(update_label_text)
...
计时器重新初始化,但似乎从未调用update_label_colors函数。
重现该行为的最小示例:启动程序,然后按键盘上的o停止计时器。然后按l重新启动,您将看到标签不再更新。
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication
from pynput import keyboard
def on_press(key):
if key.char == 'o':
stop_build_timer()
if key.char == 'l':
start_build_timer()
def stop_build_timer():
global timer, elapsed_time
if timer:
timer.stop()
timer.deleteLater()
elapsed_time = 0
update_label_text()
def start_build_timer():
global timer, elapsed_time
elapsed_time = 0
# create a new timer object
timer = QtCore.QTimer()
# connect the timer to the update function
timer.timeout.connect(update_label_text)
# start the timer with an interval of 1000 milliseconds (1 second)
timer.start(1000)
def update_label_text():
global elapsed_time
elapsed_time += 1
label.setText(f'Elapsed time: {elapsed_time} seconds')
elapsed_time = 0
app = QApplication(sys.argv)
window = QtWidgets.QWidget()
window.setGeometry(100, 100, 300, 200)
layout = QtWidgets.QVBoxLayout(window)
label = QtWidgets.QLabel('Elapsed time: 0 seconds')
layout.addWidget(label)
timer = QtCore.QTimer()
timer.timeout.connect(update_label_text)
timer.start(1000)
listener = keyboard.Listener(on_press=on_press)
listener.start()
window.show()
sys.exit(app.exec_())
Carl HR在评论中提到,当按o或l键时,他们会在终端中收到错误消息:
QObject::killTimer: Timers cannot be stopped from another thread
QObject::startTimer: Timers can only be used with threads started with QThread
由于某种原因,我在pycharm中运行测试程序时没有得到这些,但这表明计时器没有从正确的主线程中调用。我知道PyQT5中有内置的方法来添加计时器的快捷方式。遗憾的是,我需要使用另一个库,如pyinput,因为我还需要捕获窗口不在焦点上时发生的击键。
1条答案
按热度按时间luaexgnf1#
注意:我不知道这个答案是否适用,因为即使应用程序工作时没有任何崩溃(至少在我的PC上),我以前从未测试过这种方法。
为了从PyQt5线程到主线程进行通信,必须使用PyqtSignal。根据文档,我们可以使用
QueuedConnection
连接以安全的方式在线程之间传递数据。但是从我在互联网上看到的关于 * 在qt5上多线程化 * 主题的所有示例来看,只有使用QThreads
的示例。这让我产生了疑问:这真的适用于所有类型的线程,还是只适用于QThreads
?在文档中,它没有指定需要使用Qt API创建这些线程的任何地方。因此,理论上,这种方法应该适用于所有类型的线程(甚至来自其他模块)。如果这是真的,那就太有趣了。
所以,如果我们把它付诸实践,这就是你的最小可再现示例的修改版本:
当执行它时,计时器应该停止和启动没有问题。如果发生崩溃,请在评论中发布发生了什么:)