I'm making my firsts steps into python/pyqt5 world, and trying to develop an application. The app has an MDI approach, and the main functionality is already accomplished and seems to work fine (up to now).
A subwindow that contains a database table (T1) is opened at the very beginning of the app, from this window another subwindow that contains a dialog (D1) can be opened to enter record data to this table.
After this, i added a development almost similar in behaviour as the described above (a window that contains a table (T2) from which a dialog is opened (D2) to enter record data).
The point is that the window that containts T2 and the window that contains D2 seems to have focus at the same time.
At this point, if D2 is closed the window D2 AND T2 are closed.
If T1 is clicked (taking focus away of D2 or T2) and then D2 is clicked again focus is taken by D2 correctly, and if D2 is closed ... it closes as expected.
I will post some code for your guidance.
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setObjectName("MainWindow")
self.centralwidget.setObjectName("centralwidget")
self.mdiArea = QMdiArea(self.centralwidget)
self.mdiArea.setObjectName("mdiArea")
self.mdiArea.setActivationOrder(QMdiArea.ActivationHistoryOrder)
self.setCentralWidget(self.mdiArea)
globvar.mdiArea = self.mdiArea
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setObjectName("MainWindow")
self.centralwidget = QWidget(self)
self.centralwidget.setObjectName("centralwidget")
self.mdiArea = QMdiArea(self.centralwidget)
self.mdiArea.setObjectName("mdiArea")
self.mdiArea.setActivationOrder(QMdiArea.ActivationHistoryOrder)
self.setCentralWidget(self.mdiArea)
globvar.mdiArea = self.mdiArea
To copy to clipboard, switch view to plain text mode
globvar is a module that contains global variables (mdiarea, winlist). winlist is an instance of the class WindowList that let us control not to open twice the same window. This class has two methods, add and remove both return a boolean reporting the success status.
Here is the call of the T1 -> ImpABM made from the MainWindow class.
def ImpABM(self):
if globvar.winList.add('MdiIMP'):
child = modimpo.MdiIMP(self)
globvar.mdiArea.addSubWindow(child)
child.show()
def ImpABM(self):
if globvar.winList.add('MdiIMP'):
child = modimpo.MdiIMP(self)
globvar.mdiArea.addSubWindow(child)
child.show()
To copy to clipboard, switch view to plain text mode
And the call of the T2 --> ProvABM from the MainWindow class
def CliABM(self):
if globvar.winList.add('ABMfmcli'):
tabla = modabm.tabla( "fmcli", "Clientes")
tabla.addField(modabm.campo("cliid", "N", 6, "Código", "999999"))
tabla.addField(modabm.campo("clidesc", "C", 60, "Descripción" ))
tabla.isSequence("cliid", True)
tabla.orden = "clidesc"
self.cli = modabm.abmMaestros( self, tabla )
globvar.mdiArea.addSubWindow( self.cli )
self.cli.setPos(20, 20)
self.cli.setSize(500, 200)
self.cli.cargaDatos()
self.cli.show()
def CliABM(self):
if globvar.winList.add('ABMfmcli'):
tabla = modabm.tabla( "fmcli", "Clientes")
tabla.addField(modabm.campo("cliid", "N", 6, "Código", "999999"))
tabla.addField(modabm.campo("clidesc", "C", 60, "Descripción" ))
tabla.isSequence("cliid", True)
tabla.orden = "clidesc"
self.cli = modabm.abmMaestros( self, tabla )
globvar.mdiArea.addSubWindow( self.cli )
self.cli.setPos(20, 20)
self.cli.setSize(500, 200)
self.cli.cargaDatos()
self.cli.show()
To copy to clipboard, switch view to plain text mode
In module file modimpo, the class MdiIMP is defined as follow
def __init__(self, parent=None):
super(MdiImp, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
self.objectName = "MdiImp"
...
def closeEvent(self, event):
globvar.winList.remove( 'MdiImp' )
class MdiImp(QDialog):
def __init__(self, parent=None):
super(MdiImp, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
self.objectName = "MdiImp"
...
def closeEvent(self, event):
globvar.winList.remove( 'MdiImp' )
To copy to clipboard, switch view to plain text mode
In the class MdiIMP a call to D1 -> dialgImpo is made.
def ImpoAlta(self):
if globvar.winList.add( 'dialgImpo' ):
d = dialgImpo( self, "A" )
globvar.mdiArea.addSubWindow( d )
d.updTabla.connect( self.LoadTabla )
d.show()
def ImpoAlta(self):
if globvar.winList.add( 'dialgImpo' ):
d = dialgImpo( self, "A" )
globvar.mdiArea.addSubWindow( d )
d.updTabla.connect( self.LoadTabla )
d.show()
To copy to clipboard, switch view to plain text mode
The dialgImpo class is as follow :
updTabla = pyqtSignal()
def __init__(self, parent=None, accion="" ):
super(dialgImpo, self).__init__(parent)
...
self.cancela.setObjectName("cancela")
self.cancela.clicked.connect( globvar.mdiArea.closeActiveSubWindow )
...
def closeEvent( self, event ):
globvar.winList.remove( 'dialgImpo' )
globvar.mdiArea.closeActiveSubWindow()
class dialgImpo(QDialog):
updTabla = pyqtSignal()
def __init__(self, parent=None, accion="" ):
super(dialgImpo, self).__init__(parent)
...
self.cancela = QtGui.QPushButton(self)
self.cancela.setObjectName("cancela")
self.cancela.clicked.connect( globvar.mdiArea.closeActiveSubWindow )
...
def closeEvent( self, event ):
globvar.winList.remove( 'dialgImpo' )
globvar.mdiArea.closeActiveSubWindow()
To copy to clipboard, switch view to plain text mode
Up to now, seems to work fine.
Having in mind the idea of creating a master file maintenance class, i've developed the modabm module that contains the tabla (table) class that has a list of instances of campo (field) class, also defined in this module. The tabla class creates a table view of a master file based on a list of fields, as seen above in the ProvABM method.
lista = ()
def __init__(self, parent=None, nom="", desc=""):
super(tabla, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
self.nombre = nom
...
def closeEvent(self, event):
globvar.winList.remove('ABM' + self.nombre)
class tabla(QDialog):
lista = ()
def __init__(self, parent=None, nom="", desc=""):
super(tabla, self).__init__(parent)
self.setAttribute(Qt.WA_DeleteOnClose)
self.nombre = nom
...
def closeEvent(self, event):
globvar.winList.remove('ABM' + self.nombre)
To copy to clipboard, switch view to plain text mode
This window closes properly (till here everything is fine).
In the tabla class there is a method that creates a dialog based on the field definition to enter the record data.
def AltaRec(self):
if globvar.winList.add('dialgABM' + self.nombre):
debug("-- Dialogo ABM AltaRec " + self.nombre)
capturafm = dialgABM(self, ABM_ALTA, self.desc, self.campos, self.dialgx, self.dialgy, self.nombre)
globvar.mdiArea.addSubWindow(capturafm)
capturafm.show()
def AltaRec(self):
if globvar.winList.add('dialgABM' + self.nombre):
debug("-- Dialogo ABM AltaRec " + self.nombre)
capturafm = dialgABM(self, ABM_ALTA, self.desc, self.campos, self.dialgx, self.dialgy, self.nombre)
globvar.mdiArea.addSubWindow(capturafm)
capturafm.show()
To copy to clipboard, switch view to plain text mode
Here is the definition of D2 -> dialgABM class (the one that is creating problems).
commitRec = QtCore.Signal()
def __init__(self, parent=None, accion='', titulo='', campos=[], x=0, y=0, nombre=''):
super(dialgABM, self).__init__(parent)
...
self.cancela.clicked.connect(globvar.mdiArea.closeActiveSubWindow)
...
def closeEvent(self, event):
globvar.mdiArea.closeActiveSubWindow()
globvar.winList.remove('dialgABM' + self.nomtabla)
class dialgABM(QtGui.QDialog):
commitRec = QtCore.Signal()
def __init__(self, parent=None, accion='', titulo='', campos=[], x=0, y=0, nombre=''):
super(dialgABM, self).__init__(parent)
...
self.cancela.clicked.connect(globvar.mdiArea.closeActiveSubWindow)
...
def closeEvent(self, event):
globvar.mdiArea.closeActiveSubWindow()
globvar.winList.remove('dialgABM' + self.nomtabla)
To copy to clipboard, switch view to plain text mode
When closing the windows using the X button D2 AND T2 are closed.
When pressing the cancela button, T2 is closed.
When pressing the confirma button, T2 is closed too.
It seems that the T2 table is the "current" window when D2 is closed.
Tried (with no success) to setActiveWindow the D2 dialog.
Any help to solve this issue will be appreciated. I have not posted all the code because doesn't make sense.
If someone could be interested in this development, please let me know, there is no problem sharing it.
Thanks in advance
Bookmarks