【问题标题】:PyQt4 window closes automaticallyPyQt4 窗口自动关闭
【发布时间】:2016-05-16 15:42:11
【问题描述】:

我一直在开发一个 PyQt4 应用程序,这就是我目前所拥有的:

 import sys
from PyQt4 import QtGui, QtCore

class PasswordPrompt(QtGui.QWidget):

    def __init__(self):
        super(PasswordPrompt, self).__init__()
        self.initUi()

    def initUi(self):
        self.setFixedSize(500, 75)
        self.setWindowTitle('Please enter the password...')

        self.prompt = QtGui.QLineEdit(self)
        self.btn = QtGui.QPushButton('Enter', self)
        self.btn.clicked.connect(self.btnClicked)

        self.hbox = QtGui.QHBoxLayout()
        self.hbox.addWidget(self.prompt)
        self.hbox.addWidget(self.btn)

        self.vbox = QtGui.QVBoxLayout()
        self.vbox.addLayout(self.hbox)
        self.vbox2 = QtGui.QVBoxLayout()

        self.vbox2.addSpacing(300)
        self.hbox2 = QtGui.QHBoxLayout()
        self.hbox2.addSpacing(150)
        self.vbox2.addLayout(self.hbox2)

        self.vbox.addLayout(self.vbox2)

        self.setLayout(self.vbox)
        self.center()
        self.show()

    def btnClicked(self):
        pw = self.prompt.text()

        if pw == "password":
            print("Permission granted!")
            self.close()
            mw = MainWindow()

        else:
            print("Permissed denied!")
            self.prompt.clear()
            self.warningText = QtGui.QLabel('That is the wrong password!', self)
            self.hbox2.addWidget(self.warningText)

    def center(self):
        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

class MainWindow(QtGui.QWidget):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUi()

    def initUi(self):
        self.setWindowTitle('Main Menu')
        self.setFixedSize(1000, 800)

        self.show()

def main():
    application = QtGui.QApplication(sys.argv)
    p = PasswordPrompt()
    sys.exit(application.exec())


if __name__=='__main__':
    main()

当我尝试创建主窗口类的 mw 时,我的问题就出现了。出于某种原因,它会执行 MainWindow.initui() 然后立即关闭。我认为它与 main() 函数和 QApplication 对象有关。编写多个窗口并解决此问题的最佳方法是什么?我最初打算为每个窗口创建一个类:passwordPrompt、MainMenu 等,然后实例化每个类的一个实例以加载一个新窗口,但您可以看到它不起作用。

【问题讨论】:

  • 嗨@WewLad,您觉得其中一个答案有帮助吗?希望你的问题得到解决:-)

标签: python user-interface pyqt4


【解决方案1】:

我稍微调整了您的代码。我相信它现在有效:

import sys
import time
from PyQt4 import QtGui, QtCore

# Create two global variables:
p = None    
mw = None


# Create the class 'Communicate'. The instance
# from this class shall be used later on for the
# signal/slot mechanism.
class Communicate(QtCore.QObject):
    myGUI_signal = QtCore.pyqtSignal(str)

''' End class '''


class PasswordPrompt(QtGui.QWidget):

    def __init__(self):
        super(PasswordPrompt, self).__init__()
        self.initUi()
        self.mySrc = Communicate()
        self.mySrc.myGUI_signal.connect(startMainWindow) 

    def initUi(self):
        self.setFixedSize(500, 75)
        self.setWindowTitle('Please enter the password...')

        self.prompt = QtGui.QLineEdit(self)
        self.btn = QtGui.QPushButton('Enter', self)
        self.btn.clicked.connect(self.btnClicked)

        self.hbox = QtGui.QHBoxLayout()
        self.hbox.addWidget(self.prompt)
        self.hbox.addWidget(self.btn)

        self.vbox = QtGui.QVBoxLayout()
        self.vbox.addLayout(self.hbox)
        self.vbox2 = QtGui.QVBoxLayout()

        self.vbox2.addSpacing(300)
        self.hbox2 = QtGui.QHBoxLayout()
        self.hbox2.addSpacing(150)
        self.vbox2.addLayout(self.hbox2)

        self.vbox.addLayout(self.vbox2)

        self.setLayout(self.vbox)
        self.center()
        self.show()

    def btnClicked(self):
        pw = self.prompt.text()

        if pw == "password":
            print("Permission granted!")
            # self.close()
            self.mySrc.myGUI_signal.emit("password")


        else:
            print("Permissed denied!")
            self.prompt.clear()
            self.warningText = QtGui.QLabel('That is the wrong password!', self)
            self.hbox2.addWidget(self.warningText)

    def center(self):
        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

''' End class '''


class MainWindow(QtGui.QWidget):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUi()

    def initUi(self):
        self.setWindowTitle('Main Menu')
        self.setFixedSize(1000, 800)

        self.show()

''' End class '''

def main():
    global p
    application = QtGui.QApplication(sys.argv)
    p = PasswordPrompt()
    sys.exit(application.exec())

def startMainWindow(passw):
    global mw
    global p
    if(passw == "password"):
        mw = MainWindow()
        p.close()
    else:
        pass


if __name__=='__main__':
    main()

我在PasswordPrompt 类中添加了一个额外的变量:mySrc 变量。通过所谓的“信号槽”机制,我将mySrc 变量连接到函数startMainWindow(passw)。如果您想了解有关信号槽机制的更多信息,以及它如何帮助您以线程安全的方式与 GUI 进行通信,请查看这篇文章:

Simplest way for PyQT Threading

在这种特殊情况下,信号槽机制可能有点矫枉过正,因为您没有创建其他线程。但无论如何,它有效:-)。在函数startMainWindow(passw) 中,我创建了主窗口实例。之后,我关闭了密码提示实例。至关重要的是,这两个实例都是“全局变量”。如果主窗口mw 不是全局变量,则在函数startMainWindow(passw) 退出时它会被删除(并且窗口会立即关闭)。那是因为mw 只是该函数中的一个局部变量。

我希望这对您有所帮助。请让我知道此解决方案是否适合您。

【讨论】:

  • 我想我越读越明白这一点。
  • 太棒了 :-) 如果有什么可以帮助您的,请告诉我。
  • 哇,我只是将原始代码中的 mw 变量更改为全局变量,它的工作方式很奇怪。
  • 是的,这就是问题所在。当它是一个局部变量时,它很快就会被删除。当它是一个全局变量时,它会永远存在:-)
  • 这也是我在回答中建议的。使这些变量成为全局变量。我添加了信号/槽机制作为额外奖励。以防万一您将使用其他线程,并且您想将信号/数据发送到您的 GUI。
【解决方案2】:

所以我快速查看了您的代码。 我也尝试做类似的事情,但它也对我不起作用。 我所做的是一个 QDialog 并检查其返回的 DialogCode,如果接受则调用 MainWindow。

import sys
from PyQt4 import QtGui, QtCore

class PasswordPrompt(QtGui.QDialog):

    def __init__(self):
        super(PasswordPrompt, self).__init__()
        self.initUi()

    def initUi(self):
        self.setFixedSize(500, 75)
        self.setWindowTitle('Please enter the password...')

        self.prompt = QtGui.QLineEdit(self)
        self.btn = QtGui.QPushButton('Enter', self)
        self.btn.clicked.connect(self.btnClicked)

        self.hbox = QtGui.QHBoxLayout()
        self.hbox.addWidget(self.prompt)
        self.hbox.addWidget(self.btn)

        self.vbox = QtGui.QVBoxLayout()
        self.vbox.addLayout(self.hbox)
        self.vbox2 = QtGui.QVBoxLayout()

        self.vbox2.addSpacing(300)
        self.hbox2 = QtGui.QHBoxLayout()
        self.hbox2.addSpacing(150)
        self.vbox2.addLayout(self.hbox2)

        self.vbox.addLayout(self.vbox2)

        self.setLayout(self.vbox)
        self.center()

    def btnClicked(self):
        pw = self.prompt.text()

        if pw == "password":
            print("Permission granted!")
            self.accept()

        else:
            print("Permissed denied!")
            self.prompt.clear()
            self.warningText = QtGui.QLabel('That is the wrong password!', self)
            self.hbox2.addWidget(self.warningText)

    def center(self):
        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

class MainWindow(QtGui.QWidget):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.initUi()

    def initUi(self):
        self.setWindowTitle('Main Menu')
        self.setFixedSize(1000, 800)

        self.show()

def main():
    application = QtGui.QApplication(sys.argv)
    p = PasswordPrompt()
    if p.exec_() == QtGui.QDialog.Accepted:
        mw = MainWindow()
    sys.exit(application.exec_())


if __name__=='__main__':
    main()

我不是 PyQt4 的专家,但我用这种方法制作了一些应用程序,我认为它是完全有效的。 希望对您有所帮助!

【讨论】:

    【解决方案3】:

    修复它。在将 mw 变量分配给 MainWindow() 的实例之前,我将其初始化为全局变量。这就是我需要做的所有奇怪的事情。

    【讨论】:

    • 嗨@WewLad,因为我的回答给了你正确的方向,一点点赞将不胜感激:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    相关资源
    最近更新 更多