Skip to content
Advertisement

Open Window when Clicked on Push Button in Main Window PyQt5 Python

I have gone through the various post similar post which are having similar problems, tried out the answers also but it didn’t worked for me. So here is my problem –

I have two windows – TestBox and MailBox, when i click on the TestBox Pushbutton along with Input Path argument, it has to open the MailBox Window, This new window MailBox will send the ModifiedPath to the TestBox again when i closes the MailBox window

  1. I have created both windows in PyQt5 Tool and created ui file and then converted to the Python file using – python -m PyQt5.uic.pyuic testboxui.ui -o testboxui.py

  2. I am not touching testboxui.py or mailboxui.py file as they keep on changing any modifications done by reconverting. Instead i have created another file TestBox.py and MailBox.py to import and write functions.

Here is the producible minimal code –

TestBox.py [Main Application Code]

import os,sys
from PyQt5 import QtWidgets, QtGui, QtCore
from testboxui import Ui_TestBox
from MailBox import AppWindow_MailList

app = QtWidgets.QApplication(sys.argv)

class AppWindow_MainBox(QtWidgets.QMainWindow):
    def __init__(self):
        super(AppWindow_MainBox, self).__init__()
        self.ui = Ui_TestBox()
        self.ui.setupUi(self)
        self.ui.openbox.clicked.connect(self.fcn_maillist)

    def fcn_maillist(self):
        GetPath = os.getcwd()
        dialog  = AppWindow_MailList(self,GetPath)
        if dialog.exec_() == AppWindow_MailList.Accepted:
            GetPath = dialog.get_output()

def main():
    app = QtWidgets.QApplication(sys.argv)
    application = AppWindow_MainBox()
    application.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

testboxui.py [Generated by PyQt5 Tool directly from UI file]

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_TestBox(object):
    def setupUi(self, TestBox):
        TestBox.setObjectName("TestBox")
        TestBox.resize(647, 279)
        self.centralwidget = QtWidgets.QWidget(TestBox)
        self.centralwidget.setObjectName("centralwidget")
        self.openbox = QtWidgets.QPushButton(self.centralwidget)
        self.openbox.setGeometry(QtCore.QRect(210, 60, 231, 91))
        self.openbox.setObjectName("openbox")
        TestBox.setCentralWidget(self.centralwidget)

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

    def retranslateUi(self, TestBox):
        _translate = QtCore.QCoreApplication.translate
        TestBox.setWindowTitle(_translate("TestBox", "TestBox"))
        self.openbox.setText(_translate("TestBox", "Click Here n""To Open Another Window"))

MailBox.py [Child Application Code]

import os,sys
from PyQt5 import QtWidgets, QtGui, QtCore
from maillistui import Ui_MailList

app = QtWidgets.QApplication(sys.argv)

class AppWindow_MailList(QtWidgets.QMainWindow):
    def __init__(self,RcvPath=''):
        super(AppWindow_MailList, self).__init__()
        self.ui = Ui_MailList()
        self.ui.setupUi(self)
        self.init_fcn(RcvPath)

    def init_fcn(self,RcvPath):
        self.ui.browse.clicked.connect(self.browse_fcn) 
        if not RcvPath:
            self.RcvPath = os.getcwd()
        else:
            self.RcvPath = RcvPath
        self.ui.path.setText(self.RcvPath)

    def closeEvent(self, event):
        event.accept()

    def get_output(self):
        return os.path.join(self.RcvPath,'TestFolder')

    def browse_fcn(self):
        pass

def main():
    app = QtWidgets.QApplication(sys.argv)
    application = AppWindow_MailList()
    application.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

maillistui.py – [Produced by PyQt5 directly from ui file]

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MailList(object):
    def setupUi(self, MailList):
        MailList.setObjectName("MailList")
        MailList.resize(647, 279)
        self.centralwidget = QtWidgets.QWidget(MailList)
        self.centralwidget.setObjectName("centralwidget")
        self.path = QtWidgets.QLineEdit(self.centralwidget)
        self.path.setGeometry(QtCore.QRect(50, 30, 511, 41))
        self.path.setObjectName("path")
        self.browse = QtWidgets.QPushButton(self.centralwidget)
        self.browse.setGeometry(QtCore.QRect(450, 90, 112, 41))
        self.browse.setObjectName("browse")
        MailList.setCentralWidget(self.centralwidget)

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

    def retranslateUi(self, MailList):
        _translate = QtCore.QCoreApplication.translate
        MailList.setWindowTitle(_translate("MailList", "MailList"))
        self.browse.setText(_translate("MailList", "Browse"))

Previously i used to make the PyQt5 dialog with QtWidgets.QDialog which i am able to load easily in QtWidgets.QApplication. But here both are QApplication (QMainWindow) but makes to difficult to call ui within UI.

Is there any thing wrong i am doing here ???

Advertisement

Answer

Only one QApplication should be created, in your case for each script you create 2 unnecessarily, eliminate the following codes:

```
from MailBox import AppWindow_MailList

app = QtWidgets.QApplication(sys.argv) # <--- delete this line

class AppWindow_MainBox(QtWidgets.QMainWindow):
```

```
from maillistui import Ui_MailList

app = QtWidgets.QApplication(sys.argv) # <--- delete this line

class AppWindow_MailList(QtWidgets.QMainWindow):
```

Correcting the above, another error occurs but for this Python points out the error messages, in the case of many IDEs they do not handle Qt errors, so I recommend you run it in the console and you will get the following error message:

Traceback (most recent call last):
  File "TextBox.py", line 16, in fcn_maillist
    dialog  = AppWindow_MailList(self,GetPath)
TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given

Which clearly indicates that the AppWindow_MailList class accepts a single parameter(RcvPath) but you pass it 2. I do not know if it is a typo or if you do not know the use of “self” in python (if it is the latter then it is recommended to read What is the purpose of the word ‘self’?)

class AppWindow_MailList(QtWidgets.QMainWindow):
    def __init__(self,RcvPath=''):
        super(AppWindow_MailList, self).__init__()

Even solving that error there is another problem, AppWindow_MailList is a QMainWindow so it does not have any exec_() method, it seems that you have tried to use the code of some post that uses QDialog without understanding the logic of the solution.

In general, each widget has a purpose:

  • A QWidget is a generic widget that can be used as a base to build any other type of widget or container, similar to the divs in html.

  • A QDialog is a widget whose purpose is to request information from the user, so the exec_ () method returns the status of the request (if it was accepted or rejected) blocking the eventloop.

  • A QMainWindow has the purpose of offering a main window since it contains a toolbars, statusbar, menubar, dockwidets, etc.

So to implement your objective you have to choose the right elements, considering that I will restructure your application.

mailbox.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>461</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0" colspan="2">
    <widget class="QLineEdit" name="mail_le">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>49</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>16777215</width>
       <height>40</height>
      </size>
     </property>
    </widget>
   </item>
   <item row="1" column="0">
    <spacer name="horizontalSpacer">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>324</width>
       <height>20</height>
      </size>
     </property>
    </spacer>
   </item>
   <item row="1" column="1">
    <widget class="QPushButton" name="browse_btn">
     <property name="minimumSize">
      <size>
       <width>110</width>
       <height>40</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>16777215</width>
       <height>110</height>
      </size>
     </property>
     <property name="text">
      <string>Browse</string>
     </property>
    </widget>
   </item>
   <item row="2" column="1">
    <spacer name="verticalSpacer">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>20</width>
       <height>178</height>
      </size>
     </property>
    </spacer>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

testbox.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>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="1">
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
        <height>213</height>
       </size>
      </property>
     </spacer>
    </item>
    <item row="1" column="0">
     <spacer name="horizontalSpacer">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>267</width>
        <height>20</height>
       </size>
      </property>
     </spacer>
    </item>
    <item row="1" column="1">
     <widget class="QPushButton" name="open_btn">
      <property name="minimumSize">
       <size>
        <width>230</width>
        <height>90</height>
       </size>
      </property>
      <property name="maximumSize">
       <size>
        <width>230</width>
        <height>90</height>
       </size>
      </property>
      <property name="text">
       <string>Click Here 
To Open Another Window</string>
      </property>
     </widget>
    </item>
    <item row="1" column="2">
     <spacer name="horizontalSpacer_2">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>267</width>
        <height>20</height>
       </size>
      </property>
     </spacer>
    </item>
    <item row="2" column="1">
     <spacer name="verticalSpacer_2">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
        <height>212</height>
       </size>
      </property>
     </spacer>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

python -m PyQt5.uic.pyuic mailbox.ui -o mailbox_ui.py -x 
python -m PyQt5.uic.pyuic testbox.ui -o testbox_ui.py -x 

mailbox.py

import os
from PyQt5 import QtCore, QtGui, QtWidgets

from mailbox_ui import Ui_Dialog


class MailBox(QtWidgets.QDialog):
    def __init__(self, mail="", parent=None):
        super().__init__(parent)

        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

        self.ui.browse_btn.clicked.connect(self.accept)

        if mail:
            self.ui.mail_le.setText(mail)
        else:
            self.ui.mail_le.setText(os.getcwd())

    def mail(self):
        return self.ui.mail_le.text()


def main():
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MailBox()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

testbox.py

import os
from PyQt5 import QtCore, QtGui, QtWidgets

from mailbox import MailBox
from testbox_ui import Ui_MainWindow


class TestBox(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.open_btn.clicked.connect(self.open_window)

    @QtCore.pyqtSlot()
    def open_window(self):
        dialog = MailBox()
        if dialog.exec_() == QtWidgets.QDialog.Accepted:
            path = dialog.mail()
            print(path)


def main():
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = TestBox()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

├── mailbox.py
├── mailbox.ui
├── mailbox_ui.py
├── testbox.py
├── testbox.ui
└── testbox_ui.py

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement