1

Normally in Qt applications you would use this at the start and end of your code:

app = QtWidgets.QApplication(sys.argv)
...
app.exec_()

But in Maya, you don't use this because Qt runs on the Maya application it self. I'm sure this works the same for many other applications as well if you don't know what Maya is. That said, my code looks like this:

import sys
from PySide2 import QtWidgets, QtGui, QtCore

class Test():
    def __init__(self):
        self.open_qt()

    def open_qt(self):
        # app = QtWidgets.QApplication(sys.argv) # Don't need this in Maya
        self.window = QtWidgets.QWidget() # I tried QDialog also

        btn = QtWidgets.QPushButton("press me")
        btn.clicked.connect(self.login)

        lay = QtWidgets.QVBoxLayout()
        lay.addWidget(btn)

        self.window.setLayout(lay)
        self.window.show()

        # app.exec_() # Don't need this in Maya

    def login(self):
        print("logged in!")

print("before")
temp = Test()
print("after")

But running this in Maya I get this result:

before
after
logged in!

But I need it to be:

before
logged in!
after

If you run this code outside of Maya (and you use those two commented out lines) then you get the correct result (block above here).

How can I get the Maya Qt to also wait correctly like it would if you used QtWidgets.QApplication(sys.argv)?

Frank
  • 2,109
  • 7
  • 25
  • 48

1 Answers1

2

A QDialog might be more well suited for your needs, as it runs its own event loop that won't block the program, while waiting for the dialog to be completed.

The important thing to do is to call of its exec_() and call accept() when needed.

from PySide2 import QtWidgets, QtGui, QtCore

class Test(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Test, self).__init__(parent)
        layout = QtWidgets.QVBoxLayout(self)

        self.spinBox = QtWidgets.QSpinBox()
        layout.addWidget(self.spinBox)

        btn = QtWidgets.QPushButton("press me")
        layout.addWidget(btn)
        btn.clicked.connect(self.login)

    def login(self):
        print("logged in!")
        self.accept()


dialog = Test()
if dialog.exec_():
    print(dialog.spinBox.value())

I don't have Maya, but according to this answer you can get its main window using the maya.OpenMayaUI module and shiboken's wrapInstance().

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • I showed the example using PyQt5, but I actually use PySide2 in Maya. Does that change your code at all? (except for the top import of course) – Frank Feb 15 '21 at 10:34
  • Using your Python 2 example, I still get this error though: `'PySide2.QtWidgets.QDialog' called with wrong argument types: PySide2.QtWidgets.QDialog(SwigPyObject)`. I think you are on the right path with your concept though. – Frank Feb 15 '21 at 10:35
  • @Frank 1) I had some doubts about PyQt indeed, because as far as I knew Maya uses PySide2 (so, why are you asking about PyQt instead of PySide?) 2) I removed the last part, as I cannot test it, try using the code provided in the linked answer to get the main window (using shiboken wrapInstance) – musicamante Feb 15 '21 at 10:39
  • Thanks for your help! I got it working. I edited your answer with the working code. Just wait till it gets accepted, then you can change your answer as you'd like :) – Frank Feb 15 '21 at 10:48