หน้าต่าง PyQt4 จะปิดโดยอัตโนมัติ

ฉันทำงานกับแอปพลิเคชัน 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 ของคลาส Main Window ด้วยเหตุผลบางอย่าง มันจะทำ MainWindow.initui() แล้วปิดทันที ฉันคิดว่ามันเกี่ยวข้องกับฟังก์ชัน main() และวัตถุ QApplication วิธีที่ดีที่สุดในการเขียนโค้ดหลายหน้าต่างและแก้ไขปัญหานี้คืออะไร เดิมทีฉันกำลังจะสร้างคลาสต่อหน้าต่าง: passwordPrompt, MainMenu ฯลฯ จากนั้นสร้างอินสแตนซ์ของแต่ละคลาสเพื่อโหลดหน้าต่างใหม่ แต่อย่างที่คุณเห็นว่ามันไม่ทำงาน


person WewLad    schedule 16.05.2016    source แหล่งที่มา
comment
สวัสดี @WewLad คุณพบว่าคำตอบข้อใดข้อหนึ่งมีประโยชน์หรือไม่ หวังว่าปัญหาของคุณจะได้รับการแก้ไข :-)   -  person K.Mulier    schedule 03.07.2016


คำตอบ (3)


ฉันได้ปรับแต่งโค้ดของคุณเล็กน้อย ฉันเชื่อว่ามันใช้งานได้แล้ว:

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 ด้วยวิธีที่ปลอดภัยสำหรับเธรด โปรดดูโพสต์นี้:

วิธีที่ง่ายที่สุดสำหรับเธรด PyQT

บางทีกลไกช่องสัญญาณอาจใช้งานมากเกินไปเล็กน้อยในสถานการณ์นี้ เนื่องจากคุณไม่ได้สร้างเธรดอื่น แต่อย่างไรก็ตามมันก็ใช้งานได้ :-) ในฟังก์ชัน startMainWindow(passw) ฉันสร้างอินสแตนซ์หน้าต่างหลัก หลังจากนั้น ฉันจะปิดอินสแตนซ์พร้อมท์รหัสผ่าน จำเป็นอย่างยิ่งที่ทั้งสองกรณีจะต้องเป็น 'ตัวแปรทั่วโลก' หากหน้าต่างหลัก mw ไม่ใช่ตัวแปรร่วม หน้าต่างนั้นจะถูกลบ (และหน้าต่างจะปิดลงทันที) เมื่อฟังก์ชัน startMainWindow(passw)exits นั่นเป็นเพราะว่า mw เป็นเพียงตัวแปรท้องถิ่นในฟังก์ชันนั้น

ฉันหวังว่านี่จะช่วยคุณได้ โปรดแจ้งให้เราทราบว่าโซลูชันนี้เหมาะกับคุณหรือไม่

person K.Mulier    schedule 16.05.2016
comment
ฉันเริ่มเข้าใจสิ่งนี้มากขึ้นเรื่อย ๆ ฉันคิดว่า - person WewLad; 16.05.2016
comment
เยี่ยมมาก :-) หากมีสิ่งใดที่ฉันสามารถช่วยคุณได้ โปรดแจ้งให้เราทราบ - person K.Mulier; 16.05.2016
comment
ว้าว ฉันเพิ่งเปลี่ยนตัวแปร mw ในโค้ดดั้งเดิมของฉันเป็นโกลบอล และมันก็ใช้งานได้ค่อนข้างแปลก - person WewLad; 16.05.2016
comment
ใช่นั่นคือปัญหา เมื่อเป็นตัวแปรในเครื่อง จะถูกลบเร็วๆ นี้ เมื่อมันเป็นตัวแปรระดับโลกมันจะคงอยู่ตลอดไป :-) - person K.Mulier; 16.05.2016
comment
นั่นคือสิ่งที่ฉันแนะนำในคำตอบของฉัน เพื่อให้ตัวแปรเหล่านั้นเป็นสากล ฉันเพิ่มกลไกสัญญาณ/สล็อตเป็นโบนัสพิเศษ ในกรณีที่คุณเคยทำงานกับเธรดอื่น และคุณต้องการส่งสัญญาณ / ข้อมูลไปยัง GUI ของคุณ - person K.Mulier; 16.05.2016

ดังนั้นฉันจึงตรวจสอบโค้ดของคุณอย่างรวดเร็ว ฉันพยายามทำสิ่งที่คล้ายกัน แต่ก็ไม่ได้ผลสำหรับฉันเช่นกัน สิ่งที่ฉันสร้างแทนคือ 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 แต่ฉันสร้างแอปบางตัวด้วยวิธีนี้และฉันคิดว่ามันใช้ได้ทั้งหมด หวังว่ามันจะช่วยได้!

person Szabolcs    schedule 16.05.2016

ซ่อมมัน. ฉันเริ่มต้นตัวแปร mw เป็นตัวแปรส่วนกลางก่อนที่จะกำหนดให้กับอินสแตนซ์ของ MainWindow() นั่นคือทั้งหมดที่ฉันต้องทำอย่างแปลกประหลาด

person WewLad    schedule 16.05.2016
comment
สวัสดี @WewLad เนื่องจากคำตอบของฉันทำให้คุณไปในทิศทางที่ถูกต้อง การโหวตเพิ่มเล็กน้อยก็จะได้รับการชื่นชม :-) - person K.Mulier; 16.05.2016