Использование внешних библиотек GUI для создания пользовательских интерфейсов в Autodesk Maya - PullRequest
7 голосов
/ 29 декабря 2008

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 30 декабря 2008

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

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

для работы с текущим списком событий.

Удачи!

0 голосов
/ 15 мая 2015

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

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

0 голосов
/ 29 декабря 2008

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

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

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

...