设置 QDialog 框并保留对 QDialog 中元素的访问的最佳方法?

Best approach to setting up QDialog boxes and retain access to elements in the QDialog?

我目前运行 QDialog 的这个实现,它可以满足我的需要,但似乎不是最佳实践方法,并且存在一些我似乎无法解决的缺陷.我知道 QDialog 可以实现为 Class 或方法,但我需要能够访问 QDialog 的元素,如 QLineEditQComboBox,但我不确定如何执行此操作除了我在下面列出的代码。 QDialog 中与 QComboBox 关联的所有值都会立即应用,因此无需在 QDialog 关闭后保留它的副本。

Test.py

from PyQt5 import uic
from PyQt5.Qt import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys

Ui_MainWindow = uic.loadUiType('TestMainWindow.ui')[0]
Ui_ExampleDialog = uic.loadUiType('TestExampleDialog.ui')[0]


class ExampleDialog(QDialog, Ui_ExampleDialog):

    def __init__(self, parent=None, flags=Qt.Dialog):
        QDialog.__init__(self, parent, flags)
        self.setupUi(self)


class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None, flags=Qt.Window):
        QMainWindow.__init__(self, parent, flags)
        self.setupUi(self)
        self.setWindowTitle('MCVE')

        # THIS DOES NOT SEEM APPROPRIATE, BUT I NEED TO ACCESS
        # ELEMENTS OF THE UI FILE OUTSIDE OF 'showExampleDialog'
        self.exampleDialog = ExampleDialog()

        self.itemInfoBtn.clicked.connect(self.showExampleDialog)
        self.setupItemInfo()

    def showExampleDialog(self):
        # ACCORDING TO PYCHARM 'self' IS 'QMainWindow',
        # DO I ASSUME THAT 'parent = QMainWindow'?
        self.exampleDialog.setWindowFlags(Qt.WindowCloseButtonHint)
        self.exampleDialog.closeButton.clicked.connect(self.exampleDialog.accept)
        self.exampleDialog.exec_()  # CREATES A TASKBAR ENTRY ... BUT WHY?

    def setupItemInfo(self):
        # THIS IS AN EXAMPLE OF HOW I'M CURRENTLY ACCESSING
        # ELEMENTS OF THE `showExampleDialog' DIALOG
        val = {'Entry #3', 'Entry #2', 'Entry #1'}
        self.exampleDialog.setWindowTitle('Example Dialog')
        self.exampleDialog.exampleCombo.insertItems(0, val)
        self.exampleDialog.exampleCombo.setCurrentIndex(1)


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

TestMainWindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>282</width>
    <height>173</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QPushButton" name="itemInfoBtn">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="text">
       <string>ItemInfoBtn</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

TestExampleDialog.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="windowModality">
   <enum>Qt::ApplicationModal</enum>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>174</width>
    <height>98</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <property name="modal">
   <bool>true</bool>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLabel" name="Message">
     <property name="text">
      <string>I'm a Dialog ...</string>
     </property>
     <property name="alignment">
  <set>Qt::AlignCenter</set>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QComboBox" name="exampleCombo"/>
   </item>
   <item>
    <widget class="QPushButton" name="closeButton">
     <property name="text">
      <string>Close</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

我遇到的一个问题是 QDialogQMainWindow 旁边创建了第二个任务栏条目。这对我来说没有意义。根据我的理解,QDialog 可以是模态的也可以是无模态的,我相信我当前的实现具有模态集。考虑到这一点,PyCharm 说 self 是 QMainWindow 所以我假设它继承了应该阻止第二个任务栏条目填充的父项。也许我错了。

我遇到的另一个问题是访问 QDialog 的元素和变量,当它作为 class 实现时,我不太确定该怎么做,我的研究已经没有真正用通俗易懂的方式解释事情。

解决这个问题的最佳方法是什么,我怎样才能防止 QDialog 创建第二个任务栏条目?

这完全解决了这个问题。将 self 分配给 self.exampleDialog = ExampleDialog(self) 并更新 self.exampleDialog.setWindowFlags 以包含 self.exampleDialog.windowFlags() 消除了第二个任务栏条目。

可以使用 self.exampleDialog.<element> 访问对话框的元素,例如 self.exampleDialog.setWindowTitle('Example Dialog')

from PyQt5 import uic
from PyQt5.Qt import Qt
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
import sys

Ui_MainWindow = uic.loadUiType('TestMainWindow.ui')[0]
Ui_ExampleDialog = uic.loadUiType('TestExampleDialog.ui')[0]


class ExampleDialog(QDialog, Ui_ExampleDialog):
    def __init__(self, parent = None, flags = Qt.Dialog):
        QDialog.__init__(self, parent, flags)
        self.setupUi(self)


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent = None, flags = Qt.Window):
        QMainWindow.__init__(self, parent, flags)
        self.setupUi(self)
        self.setWindowTitle('MCVE')

        # Assign 'self' to 'ExampleDialog' so we can
        # access elements of the dialog.
        self.exampleDialog = ExampleDialog(self)

        self.itemInfoBtn.clicked.connect(self.showExampleDialog)
        self.setupItemInfo()

    def showExampleDialog(self):
        self.exampleDialog.setWindowFlags(self.exampleDialog.windowFlags() | Qt.WindowCloseButtonHint)
        self.exampleDialog.closeButton.clicked.connect(self.exampleDialog.accept)
        self.exampleDialog.exec_()  # CREATES A TASKBAR ENTRY ... BUT WHY?

    def setupItemInfo(self):
        val = {'Entry #3', 'Entry #2', 'Entry #1'}
        self.exampleDialog.setWindowTitle('Example Dialog')
        self.exampleDialog.exampleCombo.insertItems(0, val)
        self.exampleDialog.exampleCombo.setCurrentIndex(1)


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