我正在用Python构建一个简单的速度阅读器作为练习。基本上是Spritz克隆。
运行后停止printword()函数的正确方法是什么?我应该把它放在一个帖子里吗?使用线程还是QThread?我有点失落。
#!/usr/bin/env python3
from time import sleep
import sys
from PyQt4 import QtGui, QtCore
class Fastreader(QtGui.QWidget):
def __init__(self):
super(Fastreader, self).__init__()
self.initUI()
def initUI(self):
self.le = QtGui.QLineEdit(self)
self.le.setAlignment(QtCore.Qt.AlignCenter)
self.le.move(20, 20)
self.btn = QtGui.QPushButton('Play', self)
self.btn.move(20, 50)
self.btn.clicked.connect(self.printword)
self.btn = QtGui.QPushButton('Stop', self)
self.btn.move(120, 50)
self.setGeometry(300, 300, 225, 80)
self.setWindowTitle('fastreader')
self.show()
def printword(self):
cb = QtGui.QApplication.clipboard()
text = cb.text()
words_per_minute = 200
sleeptime = 60.0/words_per_minute
for word in text.split(" "):
self.le.setText(word)
self.le.repaint()
sleep(sleeptime)
def main():
app = QtGui.QApplication(sys.argv)
ex = Fastreader()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
非常感谢!
答案 0 :(得分:0)
我会使用带有回调的计时器,以避免在Qt中使用线程或睡眠。你可以尝试这样的事情:
def initUI(self):
...
self.btn = QtGui.QPushButton('Play', self)
self.btn.move(20, 50)
self.btn.clicked.connect(self.play)
self.btn = QtGui.QPushButton('Stop', self)
self.btn.move(120, 50)
self.btn.clicked.connect(self.stop)
...
def play(self):
cb = QtGui.QApplication.clipboard()
text = cb.text()
self.words = text.split(' ')
self.current_word = 0
words_per_minute = 200
# setInterval apparently takes msecs
sleeptime = 60000.0 / words_per_minute
self.timer = QtCore.QTimer(self)
self.timer.setInterval(sleeptime)
self.timer.timeout.connect(self.printword)
self.timer.start()
def stop(self):
self.timer.stop()
def printword(self):
word = self.words[self.current_word]
self.le.setText(word)
self.current_word += 1
if self.current_word == len(self.words):
self.timer.stop()
你甚至不必以这种方式调用self.le.repaint()。
答案 1 :(得分:0)
以下是我使用QThread
的解决方案,请检查。我还使用slot
和signal
机制在主线程和工作线程之间传输数据。
嗯,最初我认为以这种方式改变它很容易。但事实证明,需要做一些改变。但请将其视为使用QThread
。
from time import sleep
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Fastreader(QWidget):
def __init__(self):
super(Fastreader, self).__init__()
self.initUI()
def initUI(self):
self.le = QLineEdit(self)
self.le.setAlignment(Qt.AlignCenter)
self.le.move(20, 20)
self.btnplay = QPushButton('Play', self)
self.btnplay.move(20, 50)
self.btnstop = QPushButton('Stop', self)
self.btnstop.move(120, 50)
self.mthread = QThread() # New thread to run the Measurement Engine
self.worker = PrintWord() # Measurement Engine Object
# Transfer worker to the new thread. Calls to the worker will execute in mthread.
self.worker.moveToThread(self.mthread)
self.mthread.finished.connect(self.worker.deleteLater) # Cleanup after thread finished
self.btnplay.clicked.connect(self.worker.printword)
self.btnstop.clicked.connect(self.worker.kill, Qt.DirectConnection)
self.worker.wordshow.connect(self.showword)
self.mthread.start()
self.setGeometry(300, 300, 225, 80)
self.setWindowTitle('fastreader')
self.show()
@pyqtSlot(str)
def showword(self, word):
self.le.setText(word)
# self.le.repaint()
def closeEvent(self, event):
""" Example how to capture all window close events and perform an action before closing. It reimplements the default closeEvent"""
print("Close Event Received")
# Cleanup mthread.
self.mthread.quit()
self.mthread.wait()
# Accept the event, so that the window really closed.
# ignore() wold leave the window alive, for example if there is unsaved data.
# event.accept()
class PrintWord(QObject):
wordshow = pyqtSignal(str) # started measurement loop
def __init__(self):
self.dokill = False # Flag to interrupt the loop if needed
QObject.__init__(self) # Don't forget to call base class constructor
self.printword()
def printword(self):
cb = QApplication.clipboard()
text = cb.text()
words_per_minute = 200
sleeptime = 60.0/words_per_minute
self.dokill = False
for word in text.split(" "):
if self.dokill:
break
self.wordshow.emit(word)
sleep(sleeptime)
# print word
@pyqtSlot()
def kill(self):
""" Set loop interruption flag to exit the measurment loop """
self.dokill = True
def main():
app = QApplication(sys.argv)
ex = Fastreader()
sys.exit(app.exec_())
if __name__ == '__main__':
main()