1

I am new to pyqt.I am trying to invoke a child GUI when a button is clicked in the parent GUI. In this process, parent GUI has to wait for the child GUI to be closed by the user after selecting some inputs. But this is not happening, Parent GUI does execute the next lines after which the child GUI has been invoked. Below is the code where I am passing an argument to child GUI from parent GUI. The child GUI will return value based on OK/Cancel button click

Code:

import sys
from PyQt4 import QtGui,QtCore,Qt
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Child(QtGui.QWidget):
  def __init__(self,switches=None):
    super(Child,self).__init__()
    self.swwidget = QtGui.QWidget()
    self.swlayout = QtGui.QGridLayout()
    switches = ['abc1','def1']
    switches.sort()
    self.switches = switches

  def switchesUI(self):
    self.swwidget.setWindowModality(QtCore.Qt.ApplicationModal)
    self.swl   = len(self.switches)
    self.sw    = {}
    self.addsw = []
    print ("I am in switchesUI")
    #Add the switches to layout dynamically
    for i in range(self.swl):
        self.sw[i] = QtGui.QCheckBox(self.switches[i])
        self.swlayout.addWidget(self.sw[i],i,0)
    self.swbuttonbox = QtGui.QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel);
    self.swbuttonbox.setOrientation(QtCore.Qt.Horizontal)
    self.swlayout.addWidget(self.swbuttonbox)
    self.swwidget.setWindowTitle('Switches')
    self.swwidget.setLayout(self.swlayout)
    self.swwidget.show()
    self.connect(self.swbuttonbox,QtCore.SIGNAL("accepted()"),self.swaccept)
    self.connect(self.swbuttonbox,QtCore.SIGNAL("rejected()"),self.swreject)

  def swaccept(self):
    for i in range(self.swl):
      if self.sw[i].isChecked():
         self.addsw.append(self.switches[i])
    self.swwidget.close()
    return self.addsw

  def swreject(self):
    self.swwidget.close()
    return None

class Parent(QtGui.QWidget):
  def __init__(self):
    super(Parent,self).__init__()
    QtGui.QWidget.__init__(self)
    self.button = QtGui.QPushButton('Test', self)
    self.layout = QtGui.QVBoxLayout(self)
    self.layout.addWidget(self.button)
    self.assw = ['Test1','Test2']
    self.CH = Child(self.assw)
    self.connect(self.button,SIGNAL("clicked()"),self.popup)
    print ("Child GUI closed")

  def popup(self):
    self.CH.switchesUI()

def main():
  app = QtGui.QApplication(sys.argv)
  form = Parent()
  form.show()
  sys.exit(app.exec_())

if __name__ == '__main__':
  main()

After the button "Test" is clicked, a child GUI will pop-up. I don't want the statement "Child GUI Closed" to be printed till the child GUI is closed. Can someone suggest me how to achieve this functionality ?

SKP
  • 33
  • 6

1 Answers1

0

You have to handle closeEvent to perform operations when a window wants to close, also since your Child class inherits from QWidget which means it's a QWidget itself you dont need to create another one with self.swwidget

import sys
from PyQt4 import QtGui,QtCore,Qt
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Child(QtGui.QWidget):
  def __init__(self,switches=None):
    super(Child,self).__init__()
    # self.swwidget = QtGui.QWidget() # you don't need to do this you can add all the properties to self
    self.swlayout = QtGui.QGridLayout()
    switches = ['abc1','def1']
    switches.sort()
    self.switches = switches

  def switchesUI(self):
    self.setWindowModality(QtCore.Qt.ApplicationModal)
    self.swl   = len(self.switches)
    self.sw    = {}
    self.addsw = []
    print ("I am in switchesUI")
    #Add the switches to layout dynamically
    for i in range(self.swl):
        self.sw[i] = QtGui.QCheckBox(self.switches[i])
        self.swlayout.addWidget(self.sw[i],i,0)
    self.swbuttonbox = QtGui.QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel);
    self.swbuttonbox.setOrientation(QtCore.Qt.Horizontal)
    self.swlayout.addWidget(self.swbuttonbox)
    self.setWindowTitle('Switches')
    self.setLayout(self.swlayout)
    self.show()
    self.connect(self.swbuttonbox,QtCore.SIGNAL("accepted()"),self.swaccept)
    self.connect(self.swbuttonbox,QtCore.SIGNAL("rejected()"),self.swreject)

  def swaccept(self):
    for i in range(self.swl):
      if self.sw[i].isChecked():
         self.addsw.append(self.switches[i])
    self.close()
    return self.addsw

  def swreject(self):
    self.close()
    return None

  def closeEvent(self, event):
      print ("Child GUI closed")

class Parent(QtGui.QWidget):
  def __init__(self):
    super(Parent,self).__init__()
    QtGui.QWidget.__init__(self)
    self.button = QtGui.QPushButton('Test', self)
    self.layout = QtGui.QVBoxLayout(self)
    self.layout.addWidget(self.button)
    self.assw = ['Test1','Test2']
    self.CH = Child(self.assw)
    self.connect(self.button,SIGNAL("clicked()"),self.popup)

  def popup(self):
    self.CH.switchesUI()


def main():
  app = QtGui.QApplication(sys.argv)
  form = Parent()
  form.show()
  sys.exit(app.exec_())

if __name__ == '__main__':
  main()
danidee
  • 9,298
  • 2
  • 35
  • 55
  • Hi danidee, Thanks for your reply. I have a question here: What should I do to make the parent GUI wait till child GUI returns a value ? I mean , if i put a print statement in Parent GUI after self.CH.switchesUI() line, my parent should print this only after child GUI is closed. How can i achieve this ? – SKP Feb 18 '16 at 12:31
  • that's the default behaviour when the `self.CH.switchesUI()` the next statement after it will be executed, what exactly are you trying to implement...what you're trying to do now by blocking the `MainWindow` will probably block the main thread and make your UI unresponsive – danidee Feb 19 '16 at 03:31