如何在 Python 中创建用于 PyQt 的线程
How to create threads in Python for use with PyQt
我正在尝试了解如何在 Pyqt 中使用线程,并且我真的很难遵循任何教程,因为它们中的大多数都是基于通过 类 从头开始创建的界面。我已经使用 Qt 设计器创建了我的界面,但无法弄清楚如何 运行 使用线程处理程序并更新界面而不使其冻结。我的示例代码如下所示:
import sys
from PyQt5 import uic, QtWidgets
def task():
for i in range (1,100000):
html = ("<p style = 'color:blue;'> <b> Completed: %s <b> <p><br>") % i
window.plainTextEdit.appendHtml(html)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = uic.loadUi('test.ui')
window.show()
window.pushButton.clicked.connect(task)
sys.exit(app.exec_())
也很想添加一个进度条,它也可以 运行 在它自己的线程上。
类你需要爱,越早越好!
您想要的一个选项可能如下所示:
import sys
import threading
from PyQt5 import QtWidgets, QtCore # ,uic
def thread(my_func):
""" Runs a function in a separate thread. """
def wrapper(*args, **kwargs):
my_thread = threading.Thread(target=my_func, args=args, kwargs=kwargs)
my_thread.start()
return wrapper
@thread
def processing(signal):
""" Emulates the processing of some data. """
ind = 1
for i in range (1,10001): # +++
html = ("<p style='color:blue;'> Completed: <b>%s </b> </p> <br>") % i
QtCore.QThread.msleep(5)
ind = ind if i%100!=0 else ind+1 # +++
signal.emit(html, ind) # +++
def mySignalHandler(html, val): # Called to process a signal
plainTextEdit.appendHtml(html)
progressBar.setValue(val)
class WindowSignal(QtWidgets.QWidget):
""" New signals can be defined as class attributes using the pyqtSignal() factory. """
my_signal = QtCore.pyqtSignal(str, int, name='my_signal')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = WindowSignal()
button = QtWidgets.QPushButton("Emit your signal!", window)
button.clicked.connect(lambda: processing(window.my_signal))
# since you do not publish test.ui, I replaced it with the line below:
plainTextEdit = QtWidgets.QPlainTextEdit(window)
progressBar = QtWidgets.QProgressBar()
progressBar.setTextVisible(False)
layoutHBox = QtWidgets.QHBoxLayout()
layoutHBox.addWidget(button)
layoutHBox.addWidget(plainTextEdit)
layoutVBox = QtWidgets.QVBoxLayout()
window.setLayout(layoutVBox)
layoutVBox.addLayout(layoutHBox)
layoutVBox.addWidget(progressBar)
window.my_signal.connect(mySignalHandler, QtCore.Qt.QueuedConnection)
window.show()
sys.exit(app.exec_())
Example 2:
test.ui
是Qt Designer自动生成的主要window描述文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>12</x>
<y>12</y>
<width>371</width>
<height>281</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="button">
<property name="text">
<string>Emit your signal!</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
main.py
import sys
import threading
from PyQt5 import QtWidgets, QtCore, uic
def thread(my_func):
""" Runs a function in a separate thread. """
def wrapper(*args, **kwargs):
my_thread = threading.Thread(target=my_func, args=args, kwargs=kwargs)
my_thread.start()
return wrapper
@thread
def processing(signal):
""" Emulates the processing of some data. """
for i in range (1,101): # (1,100000)
html = ("<p style='color:blue;'> Completed: <b>%s </b> </p> <br>") % i
QtCore.QThread.msleep(10)
signal.emit(html, i) # Send a signal in which we transfer the received data
def mySignalHandler(html, val): # Called to process a signal
window.plainTextEdit.appendHtml(html)
window.progressBar.setValue(val)
class WindowSignal(QtWidgets.QWidget):
""" New signals can be defined as class attributes using the pyqtSignal() factory. """
my_signal = QtCore.pyqtSignal(str, int, name='my_signal')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = WindowSignal()
uic.loadUi('test.ui', window)
window.button.clicked.connect(lambda: processing(window.my_signal))
window.my_signal.connect(mySignalHandler, QtCore.Qt.QueuedConnection)
window.show()
sys.exit(app.exec_())
我正在尝试了解如何在 Pyqt 中使用线程,并且我真的很难遵循任何教程,因为它们中的大多数都是基于通过 类 从头开始创建的界面。我已经使用 Qt 设计器创建了我的界面,但无法弄清楚如何 运行 使用线程处理程序并更新界面而不使其冻结。我的示例代码如下所示:
import sys
from PyQt5 import uic, QtWidgets
def task():
for i in range (1,100000):
html = ("<p style = 'color:blue;'> <b> Completed: %s <b> <p><br>") % i
window.plainTextEdit.appendHtml(html)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = uic.loadUi('test.ui')
window.show()
window.pushButton.clicked.connect(task)
sys.exit(app.exec_())
也很想添加一个进度条,它也可以 运行 在它自己的线程上。
类你需要爱,越早越好! 您想要的一个选项可能如下所示:
import sys
import threading
from PyQt5 import QtWidgets, QtCore # ,uic
def thread(my_func):
""" Runs a function in a separate thread. """
def wrapper(*args, **kwargs):
my_thread = threading.Thread(target=my_func, args=args, kwargs=kwargs)
my_thread.start()
return wrapper
@thread
def processing(signal):
""" Emulates the processing of some data. """
ind = 1
for i in range (1,10001): # +++
html = ("<p style='color:blue;'> Completed: <b>%s </b> </p> <br>") % i
QtCore.QThread.msleep(5)
ind = ind if i%100!=0 else ind+1 # +++
signal.emit(html, ind) # +++
def mySignalHandler(html, val): # Called to process a signal
plainTextEdit.appendHtml(html)
progressBar.setValue(val)
class WindowSignal(QtWidgets.QWidget):
""" New signals can be defined as class attributes using the pyqtSignal() factory. """
my_signal = QtCore.pyqtSignal(str, int, name='my_signal')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = WindowSignal()
button = QtWidgets.QPushButton("Emit your signal!", window)
button.clicked.connect(lambda: processing(window.my_signal))
# since you do not publish test.ui, I replaced it with the line below:
plainTextEdit = QtWidgets.QPlainTextEdit(window)
progressBar = QtWidgets.QProgressBar()
progressBar.setTextVisible(False)
layoutHBox = QtWidgets.QHBoxLayout()
layoutHBox.addWidget(button)
layoutHBox.addWidget(plainTextEdit)
layoutVBox = QtWidgets.QVBoxLayout()
window.setLayout(layoutVBox)
layoutVBox.addLayout(layoutHBox)
layoutVBox.addWidget(progressBar)
window.my_signal.connect(mySignalHandler, QtCore.Qt.QueuedConnection)
window.show()
sys.exit(app.exec_())
Example 2:
test.ui
是Qt Designer自动生成的主要window描述文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>12</x>
<y>12</y>
<width>371</width>
<height>281</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="button">
<property name="text">
<string>Emit your signal!</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
main.py
import sys
import threading
from PyQt5 import QtWidgets, QtCore, uic
def thread(my_func):
""" Runs a function in a separate thread. """
def wrapper(*args, **kwargs):
my_thread = threading.Thread(target=my_func, args=args, kwargs=kwargs)
my_thread.start()
return wrapper
@thread
def processing(signal):
""" Emulates the processing of some data. """
for i in range (1,101): # (1,100000)
html = ("<p style='color:blue;'> Completed: <b>%s </b> </p> <br>") % i
QtCore.QThread.msleep(10)
signal.emit(html, i) # Send a signal in which we transfer the received data
def mySignalHandler(html, val): # Called to process a signal
window.plainTextEdit.appendHtml(html)
window.progressBar.setValue(val)
class WindowSignal(QtWidgets.QWidget):
""" New signals can be defined as class attributes using the pyqtSignal() factory. """
my_signal = QtCore.pyqtSignal(str, int, name='my_signal')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = WindowSignal()
uic.loadUi('test.ui', window)
window.button.clicked.connect(lambda: processing(window.my_signal))
window.my_signal.connect(mySignalHandler, QtCore.Qt.QueuedConnection)
window.show()
sys.exit(app.exec_())