简体   繁体   中英

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

I'm currently running this implementation of QDialog, which works for what I need, but doesn't seem like a best practice approach, and there are flaws that I can't seem to work around. I know QDialog can be implemented as a Class or Method, but I need to be able to access elements of QDialog like QLineEdit and QComboBox , and I'm not sure how to do this other than the code I have listed below. All of the values associated with the QComboBox in the QDialog are applied immediately, so there is no need to keep a copy of the QDialog around after it has been closed.

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>

One of the issues I have is that QDialog creates a second taskbar entry beside the QMainWindow one. This does not make sense to me. From my understanding, QDialog can be either modal or modeless, and I believe my current implementation has the modal set. With that in mind, PyCharm says self is QMainWindow so I assume that it is inheriting the parent which should prevent a second Taskbar entry from populating. Perhaps I'm wrong about that.

The other issue I have is accessing elements of the QDialog and variables when it has been implemented as a class, I'm not entire sure how to do that, and my research has not really explained things in a easy to understand way.

What would be the best way to approach this, and how can I prevent the QDialog from creating a second taskbar entry?

This fixes the issue completely. Assigning self to self.exampleDialog = ExampleDialog(self) and updating self.exampleDialog.setWindowFlags to include self.exampleDialog.windowFlags() eliminates the second taskbar entry.

Elements of the dialog can be accessed using self.exampleDialog.<element> for example 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_())

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