【发布时间】:2020-07-24 16:14:51
【问题描述】:
上下文
我正在创建一个在 Maya 中运行的 PySide2 工具。该工具正在执行许多长任务,一些修改场景(清理任务),一些创建文件(导出任务)。
因为这是一项漫长的任务,我想在它运行时显示反馈(进度条)。
问题
- 很遗憾,到目前为止,整个 UI 在执行期间似乎没有更新。
- 另外,由于我在实际代码中有奇怪的行为(Maya 永远冻结),我猜这不是线程的安全使用。
示例代码
这是一段简化的代码,显示了我到目前为止的位置。这是使用 QThread 的正确方法吗?我来自 CG 艺术家背景,而不是专业程序员,所以我可能误用或误解了我正在尝试使用的概念(线程、PySide ......)
import time
from PySide2.QtGui import *
from PySide2.QtCore import *
from PySide2.QtWidgets import *
import maya.cmds as cmds
class Application(object):
def __init__(self):
self.view = View(self)
def do_something(self, callback):
start = int(cmds.playbackOptions(q=True, min=True))
end = int(cmds.playbackOptions(q=True, max=True))
# First operation
for frame in xrange(start, end + 1):
cmds.currentTime(frame, edit=True)
# Export ...
callback(33)
time.sleep(1)
# Second operation
for frame in xrange(start, end + 1):
cmds.currentTime(frame, edit=True)
# Export ...
callback(66)
time.sleep(1)
# Third operation
for frame in xrange(start, end + 1):
cmds.currentTime(frame, edit=True)
# Export ...
callback(100)
time.sleep(1)
class View(QWidget):
def __init__(self, controller):
super(View, self).__init__()
self.controller = controller
self.thread = None
self.setLayout(QVBoxLayout())
self.progress = QLabel()
self.layout().addWidget(self.progress)
self.button = QPushButton('Do something')
self.layout().addWidget(self.button)
self.button.clicked.connect(self.do_something)
self.show()
def do_something(self):
self.thread = DoSomethingThread(self.controller)
self.thread.updated.connect(lambda progress: self.progress.setText(str(progress) + '%'))
self.thread.run()
class DoSomethingThread(QThread):
completed = Signal()
updated = Signal(int)
def __init__(self, controller, parent=None):
super(DoSomethingThread, self).__init__(parent)
self.controller = controller
def run(self):
self.controller.do_something(self.update_progress)
self.completed.emit()
def update_progress(self, progress):
self.updated.emit(int(progress))
app = Application()
【问题讨论】:
-
Maya 根本不喜欢从另一个线程修改场景数据。如果您只进行计算然后在主线程中使用结果,它就可以正常工作,但除非文档中另有说明,否则大多数 maya api 函数都不是线程安全的。所以我担心最好的办法是批量完成这些任务。保存场景,开始批处理作业并执行您喜欢的任何修改/导出选项。您可以与此批处理作业进行通信并在当前 Maya 会话中显示进度。
-
我明白了,非常感谢。那么在我的情况下,线程更像是更新我的pyside UI的解决方法,所以在这种情况下,是否有另一种方法可以在执行长时间操作时更新qt ui?因为这实际上是主要目标。