简体   繁体   中英

How to return from a Qdialog window

i have the following code to create an "About" windows

class Ui_aboutWindow(QDialog):
    def setupUi(self, aboutWindow):
        aboutWindow.setObjectName("aboutWindow")
        aboutWindow.setEnabled(True)
        aboutWindow.resize(330, 300)
        aboutWindow.setWindowTitle("About")
        #aboutWindow.setWhatsThis("")

        self.aboutText = QtWidgets.QTextBrowser(aboutWindow)
        self.aboutText.setGeometry(QtCore.QRect(20, 10, 280, 190))
        #self.aboutText.setWhatsThis("")
        self.aboutText.setAcceptRichText(False)
        self.aboutText.setObjectName("aboutText")

        self.horizontalLayoutWidget = QtWidgets.QWidget(aboutWindow)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 240, 281, 41))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.btSysinfo = QtWidgets.QPushButton(self.horizontalLayoutWidget)
        self.btSysinfo.setText("SysInfo")
        self.btSysinfo.setObjectName("btSysinfo")
        self.horizontalLayout.addWidget(self.btSysinfo)

        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)

        self.btOK = QtWidgets.QPushButton(self.horizontalLayoutWidget)
        self.btOK.setToolTip("")
        self.btOK.setWhatsThis("")
        self.btOK.setText("OK")
        self.btOK.setShortcut("")
        self.btOK.setObjectName("btOK")
        self.horizontalLayout.addWidget(self.btOK)

        # connect buttons to signal
        self.btOK.clicked.connect(self.return_ok)
        self.btSysinfo.clicked.connect(self.sysinfo)

    def return_ok(self):
            print("OK clicked")
            self.destroy()
            return

    def sysinfo(self):
            print("sysinfo clicked")
            pass

I call this from the main window like this

def aboutActionProcedure(self):
    # print("Opening a new popup window...")
    dialog = QtWidgets.QDialog()
    dialog.ui = Ui_aboutWindow()
    dialog.ui.setupUi(dialog)
    dialog.exec_()

the OK button in the about window calls the return_ok routine (verified with print statement), but the about window does not close

I do not want to use a Qmessagebox, as i want to add another nonstandard button to the window (sysInfo button)

what am i missing here?

There are some problems and misconceptions in your code.

First of all, you are not using your Ui_aboutWindow subclass, or, at least, you're not using it as you might think.
I'm under the impression that you're trying to mimic the behavior of files generated by pyuic , which is something that should be avoided: pyuic files are written as "interface layers" to build the GUI from ui files, but if you are going to create it manually you should just subclass QWidgets (or, QDialog, in your case) without using setupUi like that.

The problem is that using setupUi with the new QDialog instance you created, the self in the return_ok and sysinfo functions actually refers to the Ui_aboutWindow instance you created, but what you're actually showing and "setting up" is the dialog instance of QDialog created in the aboutActionProcedure function. So, destroy will actually try to destroy the Ui_aboutWindow instance (which was never shown).

Other notes and issues:

  • a layout manager should always be set for the top level widget;
  • you can use a QMessageBox even if you need a custom button: just use addButton() ;
  • you can use a QDialogButttonBox for dialog buttons and, just like the message box, add a custom button using addButton() with a specific role (for custom uses, ActionRole might be the best choice);
  • destroy() is not the right method to close a window, use close() instead (read more about the difference );
  • to correctly return a QDialog that has been exec uted, you should not call close , but use one of the existing functions instead: accept() , reject() , or done(r) ;

Here's a much simpler and cleaner way to achieve what you want:

from PyQt5 import QtWidgets

class AboutWindow(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.resize(330, 300)
        self.setWindowTitle("About")

        layout = QtWidgets.QVBoxLayout(self)

        self.aboutText = QtWidgets.QTextBrowser()
        self.aboutText.setAcceptRichText(False)
        layout.addWidget(self.aboutText)

        self.buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok)
        layout.addWidget(self.buttonBox)

        self.btSysinfo = QtWidgets.QPushButton("SysInfo")
        self.buttonBox.addButton(self.btSysinfo, QtWidgets.QDialogButtonBox.ActionRole)

        self.btSysinfo.clicked.connect(self.sysinfo)
        self.buttonBox.accepted.connect(self.return_ok)
        # note that, if you don't need to do anything specific, you can also do this:
        # self.buttonBox.accepted.connect(self.accept)

    def return_ok(self):
        print("OK clicked")
        # set the dialog as "accepted" and return its exec()
        self.accept()

    def sysinfo(self):
        print("sysinfo clicked")


class Test(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QHBoxLayout(self)
        btn = QtWidgets.QPushButton('About...')
        layout.addWidget(btn)
        btn.clicked.connect(self.aboutActionProcedure)

    def aboutActionProcedure(self):
        # print("Opening a new popup window...")
        dialog = AboutWindow()
        dialog.exec_()

if __name__ == '__main__':     
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Test()
    w.show()
    sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM