我正在创建一个在Maya中运行的PySide2工具。该工具正在执行许多长任务,一些修改场景(清理任务),一些创建文件(导出任务)
因为这是一项很长的任务,所以我希望在它运行时显示反馈(进度条)
下面是一段简化的代码,显示了我到目前为止所处的位置。这是使用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 Python中很难正确使用线程(从列出的问题数here可以看出这一点)
通常有两条严格的规则需要遵守:
这显然让很多事情很难做。通常,解决方案将涉及在主线程上运行的控制操作,而其他不涉及Maya GUI或场景对象的工作正在其他地方进行。线程安全容器(如pythonQueue)可用于将已完成的工作从工作线程转移到主线程可以安全到达的位置,或者您可以使用QT信号安全地触发主线程中的工作……如果您的编程生涯进展不远,所有这些都有点棘手
好消息是,如果您希望在Maya中执行的所有工作都在场景中,那么您不会因为没有线程而损失太多。除非这些工作基本上是非Maya工作,例如使用HTTP请求获取web数据,或者将非Maya文件写入磁盘,或者其他不处理特定于Maya的数据的工作,否则添加线程将无法获得u任何其他性能。看起来您的示例正在推进时间线,进行工作,然后尝试更新PySide GUI。为此,您根本不需要线程(您也不需要单独的QApplication Maya已经是QApplication)
这里有一个非常愚蠢的例子
点击
start
会创建一个maya scriptJob,它将尝试运行名为this_is_the_work()
的函数中的任何操作。它将运行到下一个yield
语句,然后检查以确保用户没有要求取消该作业。在这两个操作之间,maya将很忙(就像在侦听器中输入一些行一样)但是,如果在出现屈服时与Maya交互,脚本将等待您。这允许在没有单独线程的情况下进行安全的用户交互,当然也不像完全单独的线程那样平滑您会注意到,这将启动
bail()
方法中的第二个scriptJob,这是因为scriptJob无法自行终止,因此我们创建了另一个scriptJob,它将在下一个空闲事件期间运行,并终止我们不想要的scriptJob这个技巧基本上就是大多数Maya基于MEL的UI在后台工作的方式。如果在侦听器中运行
cmds.scriptJob(lj=True)
,您通常会看到许多表示UI元素的ScriptJob,这些UI元素跟踪事情相关问题 更多 >
编程相关推荐