L'utilisation de bibliothèques externes de l'interface graphique pour rendre les interfaces utilisateur dans Autodesk Maya

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

Question

Je prépare de nouveaux outils Autodesk Maya. Un grand nombre des outils que je construis ont de simples interfaces graphiques pour fenêtré les animateurs et les modélisateurs à utiliser. Ces interfaces graphiques contiennent souvent ce que vous attendez normalement voir dans une fenêtre de base; étiquettes, listes, menus, boutons, textfields, etc. Cependant, il y a des limites à la complexité du UIs vous pouvez construire avec les outils disponibles, en particulier dans les types de widgets disponibles.

Je suis intéressé à utiliser certains des widgets wxPython plus avancés tels que le ListView (grille), arbres, etc. Cela impliquerait l'aide d'une complète wxFrame (fenêtre) pour afficher l'interface utilisateur tout, qui signifierait essentiellement cette fenêtre ne serait plus lié à Maya. Pas de rupture, mais cela signifie quand Maya est réduite au minimum, la fenêtre ne sera pas de même.

Je l'ai essayé quelque chose comme ça avant avec tkinter comme un test, mais a constaté qu'il avait besoin d'un MainLoop de fonctionner dans son propre fil. Ce qui est logique, mais dans mon cas, il est en conflit avec son propre fil de Maya, faisant essentiellement Maya pendre jusqu'à ce que la fenêtre est fermée. Cela est dû au fait que Maya exécute tous les scripts, qu'ils soient ou MEL Python, dans un seul thread que les principales actions GUI Maya. Ceci est d'empêcher un script à partir, par exemple, la suppression d'un objet alors qu'un autre script tente de faire un travail sur le même objet.

wxPython a cette même Méthodologies "de mainloop". Je me demande s'il y a une façon de le contourner afin qu'il puisse travailler dans Maya?

Était-ce utile?

La solution

Je ne sais pas si cela est pertinent, mais googling se présente que PyQt est assez populaire à l'intérieur de Maya. Vous pouvez essayer la technique ou ici (expliqué ici avec le code source) de créer une nouvelle threadloop via Maya et exécuter à l'intérieur de cela. Il semble Maya a un module inclus qui met en place un nouvel objet de fil, avec un QApplication intérieur:

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

, puis met en place une fonction pour traiter les événements Qt:

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

Vous pouvez probablement faire quelque chose de similaire avec wxPython ainsi. (Utils.executeDeferred est une fonction Maya.) Assurez-vous de vérifier comment créer un non-blocage GUI sur le wiki wxPython. Au lieu de processEvents (), vous aurez envie de mettre en place une boucle d'événements et vérifier les événements « en attente » dans la fonction pumpQt (? Je l'espère renommé) ci-dessus. (La source wxPython a mise en œuvre Python de MainLoop.) probablement cela doit être fait par la fonction app.Yield (), mais je ne suis pas sûr.

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()

Les documents wxPython indiquent SafeYield () est préféré . Encore une fois, cela semble que cela pourrait être une première étape, mais je ne suis pas sûr qu'il fonctionnera et ne plantera pas juste horriblement. (Il y a une discussion sur ce que vous voulez faire sur le wxPython mailing liste mais il est de quelques versions mineures il y a de WX.) il y a aussi une indication dans divers forums que cette technique provoque des problèmes avec l'entrée du clavier. Vous pouvez également essayer de faire:

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

pour faire face à la liste actuelle des événements.

Bonne chance!

Autres conseils

Je ne sais pas s'il y a un moyen de contourner un mainloop pour l'IUG, car il est nécessaire de traiter toutes les chaînes d'événements et de redessiner les files d'attente.

Mais il y a plusieurs moyens de communication inter-processus, tels que des tuyaux ou des sémaphores. Peut-être qu'il est une option de diviser votre extension Maya dans le plug-in réelle, étant serré dans MAYA, et une application distincte pour l'IUG. Ces deux pourraient utiliser de tels moyens pour communiquer et modèle d'échange d'informations entre les plug-in et IUG. Je ne suis pas sûr, cependant, si je peux vraiment recommander cette approche car elle complique très bien l'application.

Vous pouvez jeter un oeil à IPython, un shell Python interactif, dont l'équipe dev a fait quelques efforts pour l'intégrer avec wxPython. Ils ont une certaine façon d'interrompre la boucle d'événements et d'accrochage en elle pour faire leurs propres trucs.

La meilleure façon de faire est la création d'un QWidget avec ce que vous avez besoin, et l'utiliser à partir d'un MPxCommand à travers l'API C ++. De cette façon, vous avez également la possibilité d'injecter des éditeurs complets personnalisés dans Maya via scriptedPanels.

Mais si vous êtes lié à Python, PyQt est le chemin à parcourir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top