在 PyQt 中关闭窗口后如何检索属性值?

Posted

技术标签:

【中文标题】在 PyQt 中关闭窗口后如何检索属性值?【英文标题】:How to retrieve an attribute value after closing a window in PyQt? 【发布时间】:2019-05-02 20:30:14 【问题描述】:

我正在 PYQT5 的 MainWindow 中创建一个窗口。关闭新创建的窗口后,如何在主窗口中检索它的属性?我是 PYQT 的新手。如果我对在窗口内创建窗口的方法有误,请建议我

主窗口文件

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_())

在主窗口中创建了这个窗口

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_()))

我需要在 AssignmentSectionWindow 中访问 AddAssignmentWindow 的属性 FileName

【问题讨论】:

【参考方案1】:

您必须考虑 Qt/PyQt 中的以下良好实践:

不要修改 Qt Designer 生成的代码,如消息所示:#WARNING!在此文件中所做的所有更改都将丢失! 当您使用 pyuic 生成 .py 时,因为如果您修改设计,所有编写的代码都将被删除。还有一个原因是 Qt Designer 生成的类不是小部件,而是用于填充小部件的接口类。更多信息here。

如果您想制作一个用于制作表单的小部件,请使用 QDialog,因为它允许知道应用程序何时关闭,以及通过方法 exec_() 选择用户。

使用布局设置元素。

如果没有必要,不要使用 lambda 方法。

在连接到信号的函数中使用装饰@QtCore.pyqtSlot(),因为它具有docs 中指出的几个优点。

考虑到上述情况,您的项目应具有以下结构:

.
├── 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>

然后将 .ui 转换为 .py:

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

得到如下结构:

.
├── 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_())

完整的例子可见here

【讨论】:

以上是关于在 PyQt 中关闭窗口后如何检索属性值?的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止用户在 Javascript 中关闭窗口?

如何使用 Java 在 Selenium WebDriver 中关闭子浏览器窗口

winform中关闭退出和打开新窗口的几种方式

如何在 IronPython 中关闭 WPF 窗口而不关闭 .NET 应用程序

在tkinter中关闭窗口之前执行某个命令[重复]

Windows处理如果我尝试在python中关闭当前窗口,则关闭整个浏览器