Использование внешних библиотек графического интерфейса для создания пользовательских интерфейсов в Autodesk Maya

StackOverflow https://stackoverflow.com/questions/397337

Вопрос

Я разрабатываю инструменты в Autodesk Maya.Многие инструменты, которые я создаю, имеют простые оконные графические интерфейсы для использования аниматорами и моделистами.Эти графические интерфейсы часто содержат то, что вы обычно ожидаете увидеть в любом базовом окне;метки, списки, меню, кнопки, текстовые поля и т.д.Однако существуют ограничения на сложность пользовательских интерфейсов, которые вы можете создавать с помощью доступных инструментов, в частности, на типы доступных виджетов.

Я заинтересован в использовании некоторых из более продвинутых виджетов wxPython, таких как ListView (сетка), Дерево и т.д.Это потребовало бы использования полного wxFrame (окна) для отображения всего пользовательского интерфейса, что, по сути, означало бы, что окно больше не будет привязано к Maya.Не нарушает условия сделки, но это означает, что когда Maya свернута, окно не последует ее примеру.

Я уже пробовал что-то подобное раньше с tkinter в качестве теста, но обнаружил, что ему нужен MainLoop для запуска в собственном потоке.Это логично, но в моем случае это конфликтует с собственным потоком Maya, по сути, заставляя Maya зависать до тех пор, пока окно не будет закрыто.Это связано с тем, что Maya запускает все скрипты, будь то MEL или Python, в одном потоке, который используется совместно с основным графическим интерфейсом Maya.Это делается для того, чтобы один скрипт не смог, скажем, удалить объект, в то время как другой скрипт пытается выполнить работу с тем же объектом.

wxPython имеет ту же методологию "mainloop".Мне интересно, есть ли какой-нибудь способ обойти это, чтобы это могло работать в Maya?

Это было полезно?

Решение

Я не уверен, уместно ли это, но при некотором поиске в Google выясняется, что PyQt довольно популярен внутри Maya.Вы могли бы попробовать эту технику здесь или здесь (объяснено здесь с исходным кодом) создания нового threadloop через Maya и выполнения внутри него.Похоже, в Maya включен модуль, который настраивает новый объект thread с 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.Вместо processEvents() вы захотите настроить цикл событий и проверить наличие "Ожидающих" событий внутри (надеюсь, переименованного?) Функция pumpQt выше.(Источник wxPython имеет Реализация на Python из MainLoop.) Вероятно, это должно быть сделано через приложение.Функция 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 указать безопасное поле() является предпочтительным.Опять же, кажется, что это мог бы быть первый шаг, но я не уверен, что это сработает, а не просто приведет к ужасному сбою.(Есть некоторая дискуссия о том, что вы хотите сделать на Список рассылки wxPython но это из нескольких второстепенных версий wx давности.) На различных форумах также есть некоторые указания на то, что этот метод вызывает проблемы с вводом с клавиатуры.Вы также могли бы попробовать сделать:

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

чтобы разобраться с текущим списком событий.

Удачи!

Другие советы

Я не знаю, есть ли способ обойти mainloop для графического интерфейса, поскольку он необходим для обработки всех цепочек событий и очередей перерисовки.

Но существует несколько средств межпроцессной связи, таких как каналы или семафоры.Возможно, это вариант разделить ваше расширение Maya на собственно плагин, тесно связанный с maya, и отдельное приложение для графического интерфейса.Эти двое могли бы использовать такие средства для связи и обмена информацией о модели между плагином и графическим интерфейсом.Однако я не уверен, действительно ли я могу рекомендовать этот подход, потому что это очень сильно усложняет приложение.

Вы могли бы взглянуть на IPython, интерактивную оболочку Python, команда разработчиков которой приложила некоторые усилия для ее интеграции с wxPython.У них есть какой-то способ прерывать цикл событий и подключаться к нему, чтобы делать свои собственные вещи.

Лучший способ - создать QWidget с тем, что вам нужно, и использовать его из MPxCommand через C ++ API.Таким образом, у вас также есть возможность внедрить полные пользовательские редакторы в Maya с помощью scriptedPanels.

Но если вы привязаны к Python, PyQt - это правильный путь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top