Майя ждет закрытия окна Qt

Обычно в приложениях Qt вы должны использовать это в начале и в конце вашего кода:

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

Но в Maya вы не используете это, потому что Qt сам работает в приложении Maya. Я уверен, что это работает и для многих других приложений, если вы не знаете, что такое Maya. Тем не менее, мой код выглядит так:

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

Но запустив это в Maya, я получаю такой результат:

before
after
logged in!

Но мне нужно, чтобы это было:

before
logged in!
after

Если вы запустите этот код вне Maya (и вы используете эти две закомментированные строки), вы получите правильный результат (блок выше здесь).

Как заставить Maya Qt также правильно ожидать, как если бы вы использовали QtWidgets.QApplication(sys.argv)?


person Frank    schedule 15.02.2021    source источник
comment
Вам нужно ждать окна, потому что вам нужно получить некоторые данные (например, пользователь вставляет значение), необходимые для последующих вычислений?   -  person musicamante    schedule 15.02.2021
comment
Точно @musicamante! :)   -  person Frank    schedule 15.02.2021


Ответы (1)


QDialog может лучше подходить для ваших нужд, поскольку он запускает собственный цикл обработки событий, который не блокирует программу, ожидая завершения диалогового окна.

Важно сделать вызов его exec_() и вызвать < a href="https://doc.qt.io/qt-5/qdialog.html#accept" rel="nofollow noreferrer">accept() при необходимости.

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

У меня нет Maya, но согласно этот ответ вы можете получить его главное окно, используя модуль maya.OpenMayaUI и wrapInstance() shiboken.

person musicamante    schedule 15.02.2021
comment
Я показал пример с использованием PyQt5, но на самом деле я использую PySide2 в Maya. Это вообще меняет ваш код? (кроме верхнего импорта конечно) - person Frank; 15.02.2021
comment
Используя ваш пример Python 2, я все еще получаю эту ошибку: 'PySide2.QtWidgets.QDialog' called with wrong argument types: PySide2.QtWidgets.QDialog(SwigPyObject). Я думаю, что вы на правильном пути со своей концепцией. - person Frank; 15.02.2021
comment
@Frank 1) У меня действительно были некоторые сомнения по поводу PyQt, потому что, насколько я знал, Maya использует PySide2 (итак, почему вы спрашиваете о PyQt вместо PySide?) 2) Я удалил последнюю часть, так как не могу ее протестировать, попробуйте используя код, указанный в связанном ответе, чтобы получить главное окно (используя shiboken wrapInstance) - person musicamante; 15.02.2021
comment
Спасибо за вашу помощь! Я заработал. Я отредактировал ваш ответ с рабочим кодом. Просто подождите, пока он не будет принят, тогда вы можете изменить свой ответ, как хотите :) - person Frank; 15.02.2021