在 pyqt 中另一个进程 运行 时旋转动画
Spinning animation while another process is running in pyqt
我有一个简单的 pyqt5 应用程序,它读取大 *.json 文件并制作键的树列表视图。
想知道如何同时制作动画和比较长的json阅读任务。
所以我需要一个轮子在读取文件时旋转。
看起来应该是线程,但我还不熟悉
这是一个代码:
import sys
import os
import json
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QListView, QTreeWidget, QTreeWidgetItem
from PyQt5.QtCore import *
current_folder = os.path.dirname(os.path.realpath(__file__))
load_icon = os.path.join(current_folder, 'icon_load.png')
class loaderDialog(QWidget):
def __init__(self, parent=None):
super(ren_loaderDialog, self).__init__(parent)
self.initUI()
def get_values_dict(self):
"""Getting data of unique values using in tables
and making a dict of mappings for specific table
Operation can take a long time
"""
script_folder = current_folder
file_local = os.path.join(script_folder, 'attributes.json')
with open(file_local, 'r', encoding='utf-8') as fp:
data = json.load(fp)
return data
def initUI(self):
"""Set GUI and get all data for launching
"""
self.setWindowTitle('Layer loader')
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
self.grid = QGridLayout()
self.grid.setSpacing(10)
self.setGeometry(500, 500, 400, 520)
self.listView = QTreeWidget()
self.listView.setHeaderLabel('Layers')
self.setLayout(self.grid)
self.grid.addWidget(self.listView, 0, 1, 1, 2)
self.case_strings = self.get_values_dict()
self.load_data_to_tree(self.case_strings)
self.show()
def loading_fig(self):
"""Animation of rotating wheel
"""
self.spin_wheel_init = QLabel()
self.spin_wheel_init.setAlignment(QtCore.Qt.AlignCenter)
self.spin_wheel_init.setPixmap(QPixmap(load_icon))
self.grid.addWidget(self.spin_wheel_init, 0, 1, 1, 2)
angle = 0
while True:
tr = QTransform().rotate(angle)
angle = angle + 1 if angle<360 else 0
self.spin_wheel_init.setPixmap(QPixmap(load_icon).transformed(tr))
time.sleep(0.001)
QtCore.QCoreApplication.processEvents()
def load_data_to_tree(self, data):
"""Giving keys to treeview
"""
for name in data:
child = QTreeWidgetItem(self.listView)
child.setFlags(child.flags() | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable)
child.setText(0, name)
child.setCheckState(0, Qt.Unchecked)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = loaderDialog()
w.show()
sys.exit(app.exec_())
这里我需要在名为 get_values_dict
.
的函数中读取文件时使函数 loading_fig
工作
您应该避免在 UI 线程中使用循环和 sleep
。
运行 长时间函数的一种常见方法是创建另一个线程。您可以使用 QThread
Qt class(如果您愿意,也可以在 Python 中)。
要使用 QThread
,请创建一个继承自 QObject
的新 class Worker
。它将包含您的过程。然后,创建一个实例并移动它到另一个线程:
class Worker(QObject):
done = pyqtSignal(list)
def __init__(self, parent=None):
super().__init__(parent)
def doWork(self):
print("Start")
time.sleep(10)
self.done.emit(['one', 'two', 'three'])
print("done")
class loaderDialog(QWidget):
def __init__(self, parent=None):
super(loaderDialog, self).__init__(parent)
self.initUI()
self.thread = QThread(self)
self.worker = Worker()
self.worker.moveToThread(self.thread) # worker will be runned in another thread
self.worker.done.connect(self.load_data_to_tree) # Call load_data_to_tree when worker.done is emitted
self.thread.started.connect(self.worker.doWork) # Call worker.doWork when the thread starts
self.thread.start() # Start the thread (and run doWork)
对于微调器,您应该使用 QPropertyAnimation
之类的动画而不是循环。例如:
class Spinner(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAlignment(QtCore.Qt.AlignCenter)
self.pixmap = QPixmap(load_icon)
self.setFixedSize(30, 30)
self._angle = 0
self.animation = QPropertyAnimation(self, b"angle", self)
self.animation.setStartValue(0)
self.animation.setEndValue(360)
self.animation.setLoopCount(-1)
self.animation.setDuration(2000)
self.animation.start()
@pyqtProperty(int)
def angle(self):
return self._angle
@angle.setter
def angle(self, value):
self._angle = value
self.update()
def paintEvent(self, ev=None):
painter = QPainter(self)
painter.translate(15, 15)
painter.rotate(self._angle)
painter.translate(-15, -15)
painter.drawPixmap(5, 5, self.pixmap)
我有一个简单的 pyqt5 应用程序,它读取大 *.json 文件并制作键的树列表视图。 想知道如何同时制作动画和比较长的json阅读任务。 所以我需要一个轮子在读取文件时旋转。
看起来应该是线程,但我还不熟悉
这是一个代码:
import sys
import os
import json
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QListView, QTreeWidget, QTreeWidgetItem
from PyQt5.QtCore import *
current_folder = os.path.dirname(os.path.realpath(__file__))
load_icon = os.path.join(current_folder, 'icon_load.png')
class loaderDialog(QWidget):
def __init__(self, parent=None):
super(ren_loaderDialog, self).__init__(parent)
self.initUI()
def get_values_dict(self):
"""Getting data of unique values using in tables
and making a dict of mappings for specific table
Operation can take a long time
"""
script_folder = current_folder
file_local = os.path.join(script_folder, 'attributes.json')
with open(file_local, 'r', encoding='utf-8') as fp:
data = json.load(fp)
return data
def initUI(self):
"""Set GUI and get all data for launching
"""
self.setWindowTitle('Layer loader')
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
self.grid = QGridLayout()
self.grid.setSpacing(10)
self.setGeometry(500, 500, 400, 520)
self.listView = QTreeWidget()
self.listView.setHeaderLabel('Layers')
self.setLayout(self.grid)
self.grid.addWidget(self.listView, 0, 1, 1, 2)
self.case_strings = self.get_values_dict()
self.load_data_to_tree(self.case_strings)
self.show()
def loading_fig(self):
"""Animation of rotating wheel
"""
self.spin_wheel_init = QLabel()
self.spin_wheel_init.setAlignment(QtCore.Qt.AlignCenter)
self.spin_wheel_init.setPixmap(QPixmap(load_icon))
self.grid.addWidget(self.spin_wheel_init, 0, 1, 1, 2)
angle = 0
while True:
tr = QTransform().rotate(angle)
angle = angle + 1 if angle<360 else 0
self.spin_wheel_init.setPixmap(QPixmap(load_icon).transformed(tr))
time.sleep(0.001)
QtCore.QCoreApplication.processEvents()
def load_data_to_tree(self, data):
"""Giving keys to treeview
"""
for name in data:
child = QTreeWidgetItem(self.listView)
child.setFlags(child.flags() | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable)
child.setText(0, name)
child.setCheckState(0, Qt.Unchecked)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = loaderDialog()
w.show()
sys.exit(app.exec_())
这里我需要在名为 get_values_dict
.
loading_fig
工作
您应该避免在 UI 线程中使用循环和 sleep
。
运行 长时间函数的一种常见方法是创建另一个线程。您可以使用 QThread
Qt class(如果您愿意,也可以在 Python 中)。
要使用 QThread
,请创建一个继承自 QObject
的新 class Worker
。它将包含您的过程。然后,创建一个实例并移动它到另一个线程:
class Worker(QObject):
done = pyqtSignal(list)
def __init__(self, parent=None):
super().__init__(parent)
def doWork(self):
print("Start")
time.sleep(10)
self.done.emit(['one', 'two', 'three'])
print("done")
class loaderDialog(QWidget):
def __init__(self, parent=None):
super(loaderDialog, self).__init__(parent)
self.initUI()
self.thread = QThread(self)
self.worker = Worker()
self.worker.moveToThread(self.thread) # worker will be runned in another thread
self.worker.done.connect(self.load_data_to_tree) # Call load_data_to_tree when worker.done is emitted
self.thread.started.connect(self.worker.doWork) # Call worker.doWork when the thread starts
self.thread.start() # Start the thread (and run doWork)
对于微调器,您应该使用 QPropertyAnimation
之类的动画而不是循环。例如:
class Spinner(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAlignment(QtCore.Qt.AlignCenter)
self.pixmap = QPixmap(load_icon)
self.setFixedSize(30, 30)
self._angle = 0
self.animation = QPropertyAnimation(self, b"angle", self)
self.animation.setStartValue(0)
self.animation.setEndValue(360)
self.animation.setLoopCount(-1)
self.animation.setDuration(2000)
self.animation.start()
@pyqtProperty(int)
def angle(self):
return self._angle
@angle.setter
def angle(self, value):
self._angle = value
self.update()
def paintEvent(self, ev=None):
painter = QPainter(self)
painter.translate(15, 15)
painter.rotate(self._angle)
painter.translate(-15, -15)
painter.drawPixmap(5, 5, self.pixmap)