Kumar
Kumar

Reputation: 653

How to open and close my SubWindow In QMdiArea in PyQt5?

In QMidArea how to open a SubWindow? My Programs as follows. My intention to open/attach my second program in SubWindow. But Nothing Will happen. visible Only blank Window. How to resolve it?

How to attach my file in QMdi Sub-window ? and after my work, how to close the sub-window properly?

Main Programme

import sys,os
from PyQt5.QtWidgets import *
from sample_countrypage import Countrypage

class MainPage(QMainWindow):
    def __init__(self):
        super().__init__()
        self.mdi = QMdiArea()
        self.setWindowTitle(" Sample Programme")
        self.setGeometry(100,100,1600,600)
        self.Ui()
        self.show()

    def Ui(self):
        self.btn1=QPushButton("Country")
        self.btn1.setFixedSize(100, 30)
        self.btn1.clicked.connect(self.countrypage)

        self.left_layout = QVBoxLayout()
        self.main_layout = QHBoxLayout()

        self.left_layout.setContentsMargins(3,5,5,3)
        self.left_layout.addWidget(self.btn1)
        self.left_layout.addStretch()

        self.main_layout.setSpacing(5)
        self.main_layout.setContentsMargins(0,0,0,0)
        self.main_layout.addLayout(self.left_layout)
        self.main_layout.addStretch()
        self.setLayout(self.main_layout)

        widget = QWidget()
        widget.setLayout(self.main_layout)
        self.setCentralWidget(widget)

    def countrypage(self):
        print("country page")
        self.countrywindow = Countrypage()
        subwindow = QMdiSubWindow()
        subwindow.setWidget(self.countrywindow)
        self.mdi.addSubWindow(subwindow)
        # subwindow.setFixedSize(500,500)
        subwindow.show()
        

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainwindow = MainPage()
    app.setStyle("fusion")
    mainwindow.show()
    sys.exit(app.exec_())

Second Program

import sys,os
from PyQt5.QtWidgets import *

class Countrypage(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Country Page")

        self.btn1 = QPushButton("Accept")
        self.btn1.clicked.connect(self.result)
        self.btn2 = QPushButton("Re Enter")

        self.form_layout = QFormLayout()
        self.form_layout.addRow("Country",QLineEdit())
        self.form_layout.addRow("continent",QLineEdit())

        self.layout_btn = QHBoxLayout()
        self.layout_btn.addStretch()
        self.layout_btn.addWidget(self.btn1)
        self.layout_btn.addWidget(self.btn2)

        self.layout_country = QVBoxLayout()
        self.layout_country.addLayout(self.form_layout)
        self.layout_country.addLayout(self.layout_btn)
        self.layout_country.addStretch()

        self.setLayout(self.layout_country)

    def result(self):
        print("bye")
        exec .close()

if __name__=="__main__":
    app = QApplication(sys.argv)
    countrywin = Countrypage()
    countrywin.show()
    sys.exit(app.exec_())

Upvotes: 1

Views: 1408

Answers (1)

musicamante
musicamante

Reputation: 48335

First of all, there are two main issues with your code:

  1. You never added the mdi area to the main layout (and you also tried to set the layout for the QMainWindow, which is forbidden);
  2. exec is a python builtin, and has no close attribute; if you want to close the widget, you have to call self.close();

Then, the setWidget() method of QMdiSubWindow reparents the widget:

QMdiSubWindow takes temporary ownership of widget;

This means that if you want to close the sub window that contains the widget from that widget, you have to check the parent and eventually close it, as soon as you verify that it's an instance of QMdiSubWindow.

class Countrypage(QWidget):
    # ...
    def result(self):
        print("bye")
        # ensure that the parent is actually a subwindow
        if isinstance(self.parent(), QMdiSubWindow):
            self.parent().close()
        else:
            self.close()

Alternatively, you can use a custom signal and connect that when creating the subwindow.

class Countrypage(QWidget):
    closeRequested = pyqtSignal()
    # ...
    def result(self):
        print("bye")
        self.closeRequested.emit()


class MainPage(QMainWindow):
    # ...
    def countrypage(self):
        print("country page")
        self.countrywindow = Countrypage()
        subwindow = QMdiSubWindow()
        subwindow.setWidget(self.countrywindow)
        self.mdi.addSubWindow(subwindow)
        subwindow.show()
        self.countrywindow.closerequested.connect(subwindow.close)

If you want to close the active subwindow from the mdi area (or outside of it) and no matter what that sub window is, just call self.mdi.closeActiveSubWindow().

Note that if you're going to create multiple Countrypage instances, there's no point in creating an instance attribute (self.countrywindow) as it will always be overwritten as soon as another instance will be created. Adding the widget to the subwindow and that subwindow to the mdi area will automatically create a persistent reference (due to the parenting); if you need a python reference to existing pages, then create a list as an instance member in the __init__ (eg. self.pages = []) and add the new instances to that list.

Upvotes: 3

Related Questions