Search code examples
pythonpyqtpyqt5qt-designer

How to retrieve an attribute value after closing a window in PyQt?


I am creating a window inside a MainWindow in PYQT5. Once I close the new created window , how to retrieve the attributes of it in main window ? I am new to PYQT. Please suggest me if I am wrong with the approach of creating a window inside a window

MainWindow File

class AssignmentSectionWindow (object):

    courseID = ''
    semester = ''

    def __init__(self, courseID, semester):
        self.courseID = courseID
        self.semester = semester


    def setupUi(self, assignmentSection):
        assignmentSection.setObjectName("assignmentSection")
        assignmentSection.resize(665, 506)
        self.centralwidget = QtWidgets.QWidget(assignmentSection)
        self.centralwidget.setObjectName("centralwidget")
        self.assignmentLabel = QtWidgets.QLabel(self.centralwidget)
        self.assignmentLabel.setGeometry(QtCore.QRect(30, 20, 231, 31))
        self.assignmentLabel.setObjectName("assignmentLabel")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(20, 60, 591, 321))
        self.widget.setObjectName("widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.listWidget = QtWidgets.QListWidget(self.widget)
        self.listWidget.setObjectName("listWidget")
        self.horizontalLayout.addWidget(self.listWidget)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.verticalLayout.setContentsMargins(-1, 0, 0, 200)
        self.verticalLayout.setObjectName("verticalLayout")
        self.addAssignmentButton = QtWidgets.QPushButton(self.widget)
        self.addAssignmentButton.setObjectName("addAssignmentButton")
        self.verticalLayout.addWidget(self.addAssignmentButton)
        self.editAssignmentButton = QtWidgets.QPushButton(self.widget)
        self.editAssignmentButton.setObjectName("editAssignmentButton")
        self.verticalLayout.addWidget(self.editAssignmentButton)
        self.deleteAssignmentButton = QtWidgets.QPushButton(self.widget)
        self.deleteAssignmentButton.setObjectName("deleteAssignmentButton")
        self.verticalLayout.addWidget(self.deleteAssignmentButton)
        self.horizontalLayout.addLayout(self.verticalLayout)
        assignmentSection.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(assignmentSection)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 665, 22))
        self.menubar.setObjectName("menubar")
        assignmentSection.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(assignmentSection)
        self.statusbar.setObjectName("statusbar")
        assignmentSection.setStatusBar(self.statusbar)

        self.retranslateUi(assignmentSection)
        QtCore.QMetaObject.connectSlotsByName(assignmentSection)

        self.addAssignmentButton.clicked.connect(lambda: (self.addAssignment()))

    def addAssignment(self):

        self.window = QtWidgets.QMainWindow()
        self.ui = AddAssignmentWindow(self.courseID,self.semester)
        self.ui.setupUi(self.window)
        self.window
        ```
        print(self.ui.fileName)



    def editAssignment(self):
        pass


    def deleteAssignment(self):
        pass

    def retranslateUi(self, assignmentSection):
        _translate = QtCore.QCoreApplication.translate
        assignmentSection.setWindowTitle(_translate("assignmentSection", "Assignment Section"))
        self.assignmentLabel.setText(_translate("assignmentSection", "Assignments of " + CommonUtils.getCourseNameFromCourseID(self.courseID)))
        self.addAssignmentButton.setText(_translate("assignmentSection", "Add Assignment"))
        self.editAssignmentButton.setText(_translate("assignmentSection", "Edit Assignment"))
        self.deleteAssignmentButton.setText(_translate("assignmentSection", "Delete Assignment"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    assignmentSection = QtWidgets.QMainWindow()
    ui = AssignmentSectionWindow("101","Fall2019")
    ui.setupUi(assignmentSection)
    assignmentSection.show()
    sys.exit(app.exec_())

Created this window inside the main window

class AddAssignmentWindow(object):

    filePath = ''
    fileName = ''
    couresID = ''
    semester = ''

    def __init__(self, courseID, semester):
        self.courseID = courseID
        self.semester = semester

    def setupUi(self, AddAssignment):
        AddAssignment.setObjectName("AddAssignment")
        AddAssignment.resize(644, 518)
        self.centralwidget = QtWidgets.QWidget(AddAssignment)
        self.centralwidget.setObjectName("centralwidget")

        self.submitButton = QtWidgets.QPushButton(self.centralwidget)
        self.submitButton.setGeometry(QtCore.QRect(280, 400, 113, 32))
        self.submitButton.setObjectName("submitButton")

        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(30, 40, 113, 191))
        self.widget.setObjectName("widget")

        self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")

        self.assignmentNameLabel = QtWidgets.QLabel(self.widget)
        self.assignmentNameLabel.setObjectName("assignmentNameLabel")

        self.verticalLayout.addWidget(self.assignmentNameLabel)

        self.dueLabel = QtWidgets.QLabel(self.widget)
        self.dueLabel.setObjectName("dueLabel")
        self.verticalLayout.addWidget(self.dueLabel)

        self.uploadFileLabel = QtWidgets.QLabel(self.widget)
        self.uploadFileLabel.setObjectName("uploadFileLabel")
        self.verticalLayout.addWidget(self.uploadFileLabel)
        self.descriptionLabel = QtWidgets.QLabel(self.widget)
        self.descriptionLabel.setObjectName("descriptionLabel")
        self.verticalLayout.addWidget(self.descriptionLabel)
        self.widget1 = QtWidgets.QWidget(self.centralwidget)
        self.widget1.setGeometry(QtCore.QRect(160, 50, 231, 351))
        self.widget1.setObjectName("widget1")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget1)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.assignmentNameLine = QtWidgets.QLineEdit(self.widget1)
        self.assignmentNameLine.setObjectName("assignmentNameLine")
        self.verticalLayout_2.addWidget(self.assignmentNameLine)
        spacerItem = QtWidgets.QSpacerItem(20, 28, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_2.addItem(spacerItem)
        self.dueLine = QtWidgets.QDateTimeEdit(self.widget1)
        self.dueLine.setCalendarPopup(True)
        # TODO: self.dueLine.setDate(QtCore.QDateTime.currentDateTime())
        self.dueLine.setObjectName("dueLine")
        self.verticalLayout_2.addWidget(self.dueLine)
        spacerItem1 = QtWidgets.QSpacerItem(20, 18, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_2.addItem(spacerItem1)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.uploadFileNameLine = QtWidgets.QLineEdit(self.widget1)
        self.uploadFileNameLine.setObjectName("uploadFileNameLine")
        self.horizontalLayout.addWidget(self.uploadFileNameLine)
        self.browseButton = QtWidgets.QPushButton(self.widget1)
        self.browseButton.setObjectName("browseButton")
        self.horizontalLayout.addWidget(self.browseButton)
        self.verticalLayout_2.addLayout(self.horizontalLayout)
        self.desciptionText = QtWidgets.QTextEdit(self.widget1)
        self.desciptionText.setObjectName("desciptionText")
        self.verticalLayout_2.addWidget(self.desciptionText)
        spacerItem2 = QtWidgets.QSpacerItem(20, 28, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_2.addItem(spacerItem2)
        AddAssignment.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(AddAssignment)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 644, 22))
        self.menubar.setObjectName("menubar")
        AddAssignment.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(AddAssignment)
        self.statusbar.setObjectName("statusbar")
        AddAssignment.setStatusBar(self.statusbar)

        self.retranslateUi(AddAssignment)
        QtCore.QMetaObject.connectSlotsByName(AddAssignment)

        self.browseButton.clicked.connect(lambda: (self.browserFile()))

        self.submitButton.clicked.connect(lambda: (self.submitButtonFunction()))


    def browserFile(self):
        options = QFileDialog.Options()
        self.filePath, _ = QFileDialog.getOpenFileName(None, "Open file", "~/Desktop", '', '', options=options)
        if (len(self.filePath) != 0):
            print("File Path is", self.filePath)
            self.fileName = QFileInfo(self.filePath).fileName()
            self.uploadFileNameLine.setText(self.fileName)

    def submitButtonFunction(self):
        assignmentName =self.assignmentNameLine.text()
        assignmentDue = self.dueLine.text()
        description = self.desciptionText.toPlainText()
        isSucess = AssignmentDB.postAssignmentToDB(self.courseID, assignmentName, self.filePath, self.fileName, assignmentDue, description, self.semester)
        if (isSucess):
            CommonUIUtils.showSuccessMessage("Successfully added Assignment")

    def retranslateUi(self, AddAssignment):
        _translate = QtCore.QCoreApplication.translate
        AddAssignment.setWindowTitle(_translate("AddAssignment", "Add Assignment"))
        self.submitButton.setText(_translate("AddAssignment", "Submit"))
        self.assignmentNameLabel.setText(_translate("AddAssignment", "Assignment Name"))
        self.dueLabel.setText(_translate("AddAssignment", "Assignment Due"))
        self.uploadFileLabel.setText(_translate("AddAssignment", "Upload File"))
        self.descriptionLabel.setText(_translate("AddAssignment", "Description"))
        self.browseButton.setText(_translate("AddAssignment", "Browse"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    AddAssignment = QtWidgets.QMainWindow()
    ui = AddAssignmentWindow()
    ui.setupUi(AddAssignment)
    AddAssignment.show()
    sys.exit(app.exec_()))

I need to access AddAssignmentWindow's attribute FileName inside AssignmentSectionWindow


Solution

  • You must take into account the following good practices in Qt/PyQt:

    • Do not modify the code generated by Qt Designer as indicated by the message: # WARNING! All changes made in this file will be lost! When you generate the .py using pyuic because if you modify the design all the written code will be erased. Also another reason is that the class generated by Qt Designer is not a widget, but an interface class that serves to fill a widget. More information here.

    • If you want to make a widget that serves to make a form use a QDialog since it allows to know when the application is closed, and the choice of the user through the method exec_().

    • Use the layouts to set the elements.

    • Do not use the lambda method if they are not necessary.

    • Use the decoration @QtCore.pyqtSlot() in the functions that connect to the signals since it has several advantages indicated in the docs.

    Considering the above, your project should be of the following structure:

    .
    ├── AddAssignmentDialog.py
    ├── AssignmentSectionWindow.py
    └── uis
        ├── AddAssignmentDialog.ui
        └── AssignmentSectionWindow.ui
    

    AddAssignmentDialog.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>AddAssignmentDialog</class>
     <widget class="QDialog" name="AddAssignmentDialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>400</width>
        <height>300</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Dialog</string>
      </property>
      <layout class="QFormLayout" name="formLayout_4">
       <item row="0" column="0">
        <widget class="QLabel" name="assignmentNameLabel">
         <property name="text">
          <string>Assignment Name</string>
         </property>
        </widget>
       </item>
       <item row="0" column="1">
        <widget class="QLineEdit" name="assignmentNameLine"/>
       </item>
       <item row="1" column="0">
        <widget class="QLabel" name="dueLabel">
         <property name="text">
          <string>Assignment Due</string>
         </property>
        </widget>
       </item>
       <item row="1" column="1">
        <widget class="QLineEdit" name="dueLine"/>
       </item>
       <item row="2" column="0">
        <widget class="QLabel" name="uploadFileLabel">
         <property name="text">
          <string>Upload File</string>
         </property>
        </widget>
       </item>
       <item row="2" column="1">
        <layout class="QHBoxLayout" name="horizontalLayout">
         <item>
          <widget class="QLineEdit" name="uploadFileNameLine"/>
         </item>
         <item>
          <widget class="QPushButton" name="browseButton">
           <property name="text">
            <string>Browse</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
       <item row="3" column="0">
        <widget class="QLabel" name="descriptionLabel">
         <property name="text">
          <string>Description</string>
         </property>
        </widget>
       </item>
       <item row="3" column="1">
        <widget class="QTextEdit" name="descriptionText"/>
       </item>
       <item row="4" column="1">
        <layout class="QHBoxLayout" name="horizontalLayout_2">
         <item>
          <spacer name="horizontalSpacer">
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
            </size>
           </property>
          </spacer>
         </item>
         <item>
          <widget class="QPushButton" name="submitButton">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="text">
            <string>Submit</string>
           </property>
          </widget>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    AssignmentSectionWindow.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>AssignmentSectionWindow</class>
     <widget class="QMainWindow" name="AssignmentSectionWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>800</width>
        <height>600</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Assignment Section</string>
      </property>
      <widget class="QWidget" name="centralwidget">
       <layout class="QGridLayout" name="gridLayout">
        <item row="0" column="0">
         <widget class="QLabel" name="assignmentLabel">
          <property name="text">
           <string>Assignments of %n </string>
          </property>
         </widget>
        </item>
        <item row="1" column="0">
         <widget class="QListWidget" name="listWidget"/>
        </item>
        <item row="1" column="1">
         <layout class="QVBoxLayout" name="verticalLayout">
          <item>
           <widget class="QPushButton" name="addAssignmentButton">
            <property name="text">
             <string>Add Assignment</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QPushButton" name="editAssignmentButton">
            <property name="text">
             <string>Edit Assignment</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QPushButton" name="deleteAssignmentButton">
            <property name="text">
             <string>Delete Assignment</string>
            </property>
           </widget>
          </item>
          <item>
           <spacer name="verticalSpacer">
            <property name="orientation">
             <enum>Qt::Vertical</enum>
            </property>
            <property name="sizeHint" stdset="0">
             <size>
              <width>20</width>
              <height>40</height>
             </size>
            </property>
           </spacer>
          </item>
         </layout>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>800</width>
         <height>23</height>
        </rect>
       </property>
      </widget>
      <widget class="QStatusBar" name="statusbar"/>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    Then you convert the .ui to .py:

    pyuic5 uis/AddAssignmentDialog.ui -o AddAssignmentDialog_ui.py
    pyuic5 uis/AssignmentSectionWindow.ui -o AssignmentSectionWindow_ui.py
    

    Obtaining the following structure:

    .
    ├── AddAssignmentDialog.py
    ├── AddAssignmentDialog_ui.py
    ├── AssignmentSectionWindow.py
    ├── AssignmentSectionWindow_ui.py
    └── uis
        ├── AddAssignmentDialog.ui
        └── AssignmentSectionWindow.u
    

    AddAssignmentDialog.py

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    from AddAssignmentDialog_ui import Ui_AddAssignmentDialog
    
    
    class AddAssignmentDialog(QtWidgets.QDialog, Ui_AddAssignmentDialog):
        def __init__(self, parent=None):
            super(AddAssignmentDialog, self).__init__(parent)
            self.setupUi(self)
            self.filename = ""
    
            self.browseButton.clicked.connect(self.browserFile)
            self.submitButton.clicked.connect(self.accept)
    
        @QtCore.pyqtSlot()
        def browserFile(self):
            self.filename, _ = QtWidgets.QFileDialog.getOpenFileName(
                None,
                "Open file",
                QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DesktopLocation),
                "",
                "",
            )
            if self.filename:
                finfo = QtCore.QFileInfo(self.filename)
                self.uploadFileNameLine.setText(finfo.fileName())
    
        def get_assignment(self):
            assignmentName = self.assignmentNameLine.text()
            assignmentDue = self.dueLine.text()
            description = self.descriptionText.toPlainText()
            return {"name": assignmentName, "due": assignmentDue, "description": description}
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = AddAssignmentDialog()
        w.show()
        sys.exit(app.exec_())
    

    AssignmentSectionWindow.py

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    from AssignmentSectionWindow_ui import Ui_AssignmentSectionWindow
    from AddAssignmentDialog import AddAssignmentDialog
    
    
    class AssignmentSectionWindow(QtWidgets.QMainWindow, Ui_AssignmentSectionWindow):
        def __init__(self, parent=None):
            super(AssignmentSectionWindow, self).__init__(parent)
            self.setupUi(self)
            self.addAssignmentButton.clicked.connect(self.addAssignment)
            self.assignmentLabel.setText("Assignments of xxx")
    
        @QtCore.pyqtSlot()
        def addAssignment(self):
            w = AddAssignmentDialog()
            if w.exec_() == QtWidgets.QDialog.Accepted:
                data = w.get_assignment()
                print(data)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = AssignmentSectionWindow()
        w.show()
        sys.exit(app.exec_())
    

    The complete example can be found here