如果拒绝对话框,PyQt应用程序会冻结

1 投票
2 回答
1773 浏览
提问于 2025-04-18 14:17

我有一个小应用程序,在启动之前需要用户登录。可是如果用户拒绝登录(按下取消按钮),应用程序不会关闭,而是会卡住。

下面是简化后的代码:

import sys

from PyQt5 import QtWidgets, QtCore


class LoginWindow(QtWidgets.QDialog):

    def __init__(self, parent=None):
        super(LoginWindow, self).__init__(parent)
        self.resize(250, 150)
        self.move(500, 500)
        self.setWindowTitle('Login')
        self.login_input = QtWidgets.QLineEdit(self)
        self.login_input.move(10, 10)
        self.password_input = QtWidgets.QLineEdit(self)
        self.password_input.move(10, 50)
        self.password_input.setEchoMode(QtWidgets.QLineEdit.Password)
        self.button_box = QtWidgets.QDialogButtonBox(self)
        self.button_box.move(10, 80)
        self.button_box.setOrientation(QtCore.Qt.Horizontal)
        self.button_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel |
                                           QtWidgets.QDialogButtonBox.Ok)

        self.button_box.accepted.connect(self.login)
        self.button_box.rejected.connect(self.reject)

    def login(self):
        self.accept()

    def cancel(self):
        self.reject()


class MainWindow(QtWidgets.QDialog):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.resize(250, 150)
        self.move(500, 500)
        self.setWindowTitle('Main')
        self.input = QtWidgets.QLineEdit(self)
        self.input.move(10, 10)
        self.show()

def main():
    app = QtWidgets.QApplication([])
    l = LoginWindow()
    l.show()
    login_result = l.exec_()
    print(login_result)
    if login_result == QtWidgets.QDialog.Accepted:
        m = MainWindow()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

我哪里做错了?我使用的是Python 3和PyQt5。

2 个回答

1

我找到了一种方法来避免这个错误:

我修改了主函数:

def main():
    app = QtWidgets.QApplication([])
    if LoginWindow().exec_() == QtWidgets.QDialog.Accepted:
        m = MainWindow()
        sys.exit(app.exec_())

现在它正常工作了,但我还是不明白,问题的根本原因是什么。

2

这个问题发生是因为PySide还没有处理任何事件。

app.exec_()

这段代码启动了一个主事件循环,它会不断处理每一次图形界面的互动。在你执行任何图形界面代码之前,应该先调用这个循环,这样事件才能正确地从事件队列中处理。

QDialog.exec_()是一个阻塞操作,这意味着在得到响应之前,代码不会继续执行。

如果你想看到对话框里的内容,可能有办法绕过这个问题。

QtGui.QApplication.processEvents()

这段代码会处理事件队列中的所有事件,所以你可能需要不断调用这个方法。

另外,在你初始化主窗口之后,还需要把主窗口显示出来。

撰写回答