我最近想尝试使用Wing IDE而不是Eclipse + Pydev来使用PyQt5编写简单的类似rogue的游戏。该游戏使用单独的QThread及其内部的QObject处理游戏状态,而不会冻结GUI。但是,我当前的应用程序在Wing IDE中冻结,该应用程序与标准和Eclipse的解释器一起很好地工作。在这里,我发布了代表问题的简单代码:
import sys, time
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject, QThread
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLCDNumber, QVBoxLayout, QWidget
class Counter(QObject):
'''
QObject-based class which works inside separate thread and
emits numbers from 1 to 10 to the GUI thread and then stops.
'''
new_value = pyqtSignal(int)
ended = pyqtSignal()
def __init__(self):
QObject.__init__(self)
self.isStopped = False
@pyqtSlot()
def start(self):
self.isStopped = False
for n in range(1, 11):
if not self.isStopped:
self.new_value.emit(n)
time.sleep(0.3)
else:
break
self.ended.emit()
@pyqtSlot()
def stop(self):
self.isStopped = True
class SimpleWindow(QMainWindow):
'''
Application window with 3 buttons and 1 LCD display.
'''
def __init__(self):
QMainWindow.__init__(self)
# Adding and configuring widgets
self.central = QWidget(self)
self.central.resize(100, 150)
self.resize(100, 150)
self.layout = QVBoxLayout()
self.central.setLayout(self.layout)
self.start_QBtn = QPushButton()
self.start_QBtn.setText('Start')
self.stop_QBtn = QPushButton()
self.stop_QBtn.setText('Stop')
self.number_LCD = QLCDNumber()
self.status_QBtn = QPushButton()
self.status_QBtn.setText('Status')
self.layout.addWidget(self.start_QBtn)
self.layout.addWidget(self.stop_QBtn)
self.layout.addWidget(self.status_QBtn)
self.layout.addWidget(self.number_LCD)
# Creating new thread and adding QObject-based object to it
self.thread = QThread()
self.counter = Counter()
self.counter.moveToThread(self.thread)
# Connecting button signals to slots
self.start_QBtn.clicked.connect(self.thread.start)
self.status_QBtn.clicked.connect(self.status)
self.stop_QBtn.clicked.connect(lambda: self.counter.stop())
# Connecting thread signals to slots
self.counter.new_value.connect(self.show_value)
self.counter.ended.connect(self.thread.quit)
self.thread.started.connect(self.counter.start)
self.thread.start()
@pyqtSlot(int)
def show_value(self, number):
'''
Display value obtained from Counter() in the LCD widget.
'''
self.number_LCD.display(number)
@pyqtSlot()
def status(self):
'''
Print thread status in the console.
'''
print('Thread is running: ', self.thread.isRunning())
if __name__ == "__main__":
app = QApplication(sys.argv)
window = SimpleWindow()
window.show()
sys.exit(app.exec_())
应用程序启动,按预期显示从1到10的数字,然后冻结。当尝试按下“停止”按钮时,它也会冻结。是否可以通过Wing IDE继续使用QThread?
我的系统是Windows 8(x64),Python 3.7.1,Wing IDE Personal 6.1; PyQt5.11(也已与PyQt 5.7一起检查); Qt 5.7。
答案 0 :(得分:1)
我可以复制它,并且好像不能正确支持moveToThread()。这是另一个测试用例,其中包含三个测试,一个是QThread的子类,另一个是使用moveToThread()的子类,第三个是QRunnable的子类。对我来说,第一个和最后一个工作以及使用moveToThread()的那个都不起作用:
# From http://stackoverflow.com/questions/6783194/background-thread-with-qthread-in-pyqt
# with minor modifications
import time
import sys
from PyQt5 import QtCore
# Hack needed to avoid _NotifyModule bug
from PyQt5.QtCore import *
# Subclassing QThread
# http://qt-project.org/doc/latest/qthread.html
class AThread(QtCore.QThread):
def run(self):
count = 0
while count < 5:
time.sleep(1)
print("Increasing")
count += 1
# Subclassing QObject and using moveToThread
# http://blog.qt.digia.com/blog/2007/07/05/qthreads-no-longer-abstract
class SomeObject(QtCore.QObject):
finished = QtCore.pyqtSignal()
def longRunning(self):
count = 0
while count < 5:
time.sleep(1)
print("Increasing")
count += 1
self.finished.emit()
# Using a QRunnable
# http://qt-project.org/doc/latest/qthreadpool.html
# Note that a QRunnable isn't a subclass of QObject and therefore does
# not provide signals and slots.
class Runnable(QtCore.QRunnable):
def run(self):
count = 0
app = QtCore.QCoreApplication.instance()
while count < 5:
print("Increasing")
time.sleep(1)
count += 1
app.quit()
def usingQThread():
app = QtCore.QCoreApplication([])
thread = AThread()
thread.finished.connect(app.exit)
thread.start()
sys.exit(app.exec_())
def usingMoveToThread():
app = QtCore.QCoreApplication([])
objThread = QtCore.QThread()
obj = SomeObject()
obj.moveToThread(objThread)
obj.finished.connect(objThread.quit)
objThread.started.connect(obj.longRunning)
objThread.finished.connect(app.exit)
objThread.start()
sys.exit(app.exec_())
def usingQRunnable():
app = QtCore.QCoreApplication([])
runnable = Runnable()
QtCore.QThreadPool.globalInstance().start(runnable)
sys.exit(app.exec_())
if __name__ == "__main__":
usingQThread()
#usingMoveToThread()
#usingQRunnable()
请注意,您不必取消注释即可进行测试,因为它们都调用sys.exit,因此一次只能尝试其中的一个。
我将看看我们是否可以在以后的Wing版本中解决此问题。感谢您发布!!