【问题标题】:Using external GUI libraries to make user interfaces in Autodesk Maya使用外部 GUI 库在 Autodesk Maya 中制作用户界面
【发布时间】:2010-09-28 16:20:27
【问题描述】:

我在 Autodesk Maya 中开发工具。我构建的许多工具都有简单的窗口 GUI 供动画师和建模师使用。这些 GUI 通常包含您通常希望在任何基本窗口中看到的内容;标签、列表、菜单、按钮、文本字段等。但是,您可以使用可用工具构建的 UI 的复杂性受到限制,特别是可用小部件的类型。

我有兴趣使用一些更高级的 wxPython 小部件,例如 ListView(网格)、Tree 等。这将涉及使用完整的 wxFrame(窗口)来显示整个 UI,这实际上意味着该窗口将不再与玛雅联系在一起。不是破坏交易,但这意味着当 Maya 最小化时,窗口不会效仿。

我之前用 tkinter 作为测试尝试过类似的事情,但发现它需要一个 MainLoop 才能在自己的线程中运行。这是合乎逻辑的,但在我的情况下,它与 Maya 自己的线程冲突,基本上使 Maya 挂起,直到窗口关闭。这是因为 Maya 在主 Maya GUI 共享的单个线程中运行所有脚本,无论是 MEL 还是 Python。这是为了防止一个脚本在另一个脚本尝试处理同一个对象时删除一个对象。

wxPython 也有同样的“mainloop”方法。我想知道是否有任何方法可以让它在 Maya 中工作?

【问题讨论】:

    标签: python scripting wxpython wxwidgets maya


    【解决方案1】:

    我不确定这是否密切相关,但通过谷歌搜索发现 PyQt 在 Maya 中非常流行。您可以尝试通过 Maya 创建一个新的线程循环并在其中执行的技术herehere(用源代码解释here)。似乎 Maya 包含一个模块,用于设置一个新的线程对象,其中包含一个 QApplication:

    def initializePumpThread():
        global pumpedThread
        global app
        if pumpedThread == None:
            app = QtGui.QApplication(sys.argv)
            pumpedThread = threading.Thread(target = pumpQt, args = ())
            pumpedThread.start()
    

    然后设置一个函数来处理Qt事件:

    def pumpQt():
        global app
        def processor():
            app.processEvents()
        while 1:
            time.sleep(0.01)
            utils.executeDeferred( processor )
    

    你也可以用 wxPython 做类似的事情。 (utils.executeDeferred 是一个 Maya 函数。)请务必查看如何在 wxPython wiki 上创建 non-blocking GUI。您需要设置一个事件循环,而不是 processEvents(),并检查上面的(希望重命名?)pumpQt 函数中的“待处理”事件。 (wxPython 源代码有一个 Python implementation 的 MainLoop。)可能这应该通过 app.Yield() 函数完成,但我不确定。

    def pumpWx():
        global app
        def processor():
            app.Yield(True)
        while 1:
            time.sleep(0.01)
            utils.executeDeferred( processor )
    
    def initializePumpThread():
        global pumpedThread
        global app
        if pumpedThread == None:
            app = wx.App(False)
            pumpedThread = threading.Thread(target = pumpWx, args = ())
            pumpedThread.start()
    

    wxPython 文档indicate SafeYield() 是首选。同样,这似乎是第一步,但我不确定它会起作用,而不仅仅是可怕的崩溃。 (在wxPython mailing list 上有一些关于你想要做什么的讨论,但它来自 wx 之前的几个小版本。)在各种论坛中也有一些迹象表明这种技术会导致键盘输入出现问题。您也可以尝试这样做:

    def processor():
      while app.Pending(): app.Dispatch()
    

    处理当前事件列表。

    祝你好运!

    【讨论】:

    • 既然你提到它,我突然想起听说 Maya 可能会添加原生 QT 支持。所以这可能有很多优点。
    【解决方案2】:

    我不知道是否有办法绕过 gui 的主循环,因为需要它来处理所有事件链和重绘队列。

    但是有几种进程间通信方式,例如管道或信号量。也许将您的 Maya 扩展拆分为实际插件、紧密集成到 Maya 以及​​用于 gui 的单独应用程序是一种选择。这两者可以使用这种方式在插件和 gui 之间进行通信和交换模型信息。 但是,我不确定我是否真的可以推荐这种方法,因为它会使应用程序非常复杂。

    你可以看看 IPython,一个交互式 Python shell,它的开发团队已经努力将它与 wxPython 集成。他们有一些方法可以中断事件循环并连接到它来做自己的事情。

    【讨论】:

      【解决方案3】:

      最好的方法是用你需要的东西创建一个 QWidget,然后通过 C++ API 在 MPxCommand 中使用它。这样,您也有机会通过 scriptedPanels 将完整的自定义编辑器注入 Maya。

      但如果你绑定到 Python,那么 pyQt 就是你要走的路。

      【讨论】:

        猜你喜欢
        • 2011-04-29
        • 2023-02-09
        • 2022-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-13
        • 1970-01-01
        相关资源
        最近更新 更多