Hello,

What's the right way to open and close dialog windows multiple times? At the moment I instantiate a dialog window on a clicked button signal, then close it with self.close() but when I open it again Python crashes. So I can open the dialog only once. How can I open dialogs more than once? Thank you.

class MainWindow(QMainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self)
...
        self.connect(self.actionCustomFactors, SIGNAL("triggered()"), self.OnCustomFactorsTriggered)
...
    def OnCustomFactorsTriggered(self):
        self.customWin= CustomWindow()
        self.customWin.show()
        self.connect(self.customWin, SIGNAL("closed()"), self.OnCustomWinClosed)
...
    def OnCustomWinClosed(self):
        self.cbProperty.clear()
...
class CustomWindow(QMainWindow):
    def __init__(self, factorsFile, parent = None):
        QMainWindow.__init__(self)
...
        self.connect(self.btnCancel, SIGNAL("clicked()"), self.Close)
...
    def Close(self):
        self.close()
...
    def closeEvent(self, event):
        self.ClearInputs()
        self.emit(SIGNAL("closed()"))

Hey

Try this:

self.window = CustomWindow()
self.window.exec_()

or

window=CustomWindow(self) # and params
window.exec_()

Edited 6 Years Ago by -ordi-: n/a

Well, this and show()/close() still crashes it as they only close the window but they don't destroy the actual object. How can I instantiate an object and then destroy it after closing the window? At the moment this is the only code which doesn't crash but it's still not what I'm looking for:

class MainWindow(QMainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self)

        self.customWin = None
...
    def OpenNewWindow(self):
        if self.customWin:
            self.customWin.show()
        else:
            self.customWin= CustomWindow(self.factorsFile)
            self.customWin.show()
            self.connect(self.customWin, SIGNAL("closed()"), self.OnCustomWinClosed)

The above simply closes the window but keeps the object alive. How can I kill the object? What's the Python function/method/whatever to destroy an object?

What's the Python function/method/whatever to destroy an object?

Most of the tutorials for qt3 (if that is what you are using), use sys.exit().

import sys
import qt


class MyWidget(qt.QVBox):
    def __init__(self, parent=None, name=None):
        qt.QVBox.__init__(self, parent, name)

        quit = qt.QPushButton("Quit", self, "quit")
        quit.setFont(qt.QFont("Times", 18, qt.QFont.Bold))

        self.connect(quit, qt.SIGNAL("clicked()"), qt.qApp, qt.SLOT("quit()"))

        lcd = qt.QLCDNumber(2, self, "lcd")

        slider = qt.QSlider(qt.Qt.Horizontal, self, "slider")
        slider.setRange(0, 99)
        slider.setValue(0)

        self.connect(slider, qt.SIGNAL("valueChanged(int)"), lcd, qt.SLOT("display(int)"))


a = qt.QApplication(sys.argv)

w = MyWidget()
a.setMainWidget(w)
w.show()
sys.exit(a.exec_loop())

To destroy the object, assign something else to the variable.
(in pseudocode)
MW = MainWindow()
qApp.connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()))
MW = ""

If you can supply a simple example of what you want to do it would help as you may want to use setModal or closeEvent.

Edited 6 Years Ago by woooee: n/a

Please download the whole application Cute Converter and have a look at what I'm currently doing. Because I don't know how to destroy another window after closing it, I have to reset all inputs every time I close it instead of creating a new window object when required.

I tried this

def OnCustomFactorsTriggered(self):
        if self.customWin:
            self.customWin=""
        self.customWin= CustomWindow(self.factorsFile)
        self.customWin.show()
        self.connect(self.customWin, SIGNAL("closed()"), self.OnCustomWinClosed)

and this:

def OnCustomFactorsTriggered(self):
        if self.customWin:
            self.customWin=None
        self.customWin= CustomWindow(self.factorsFile)
        self.customWin.show()
        self.connect(self.customWin, SIGNAL("closed()"), self.OnCustomWinClosed)

and it crashes when I open the window the second time with "Access violation at address 6A2B2B96 in module 'QtCore4.dll'. Read of address 00000011."

Edited 6 Years Ago by linuxoidoz: n/a

Well, this and show()/close() still crashes it as they only close the window but they don't destroy the actual object. How can I instantiate an object and then destroy it after closing the window? At the moment this is the only code which doesn't crash but it's still not what I'm looking for:

class MainWindow(QMainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self)

        self.customWin = None
...
    def OpenNewWindow(self):
        if self.customWin:
            self.customWin.show()
        else:
            self.customWin= CustomWindow(self.factorsFile)
            self.customWin.show()
            self.connect(self.customWin, SIGNAL("closed()"), self.OnCustomWinClosed)

The above simply closes the window but keeps the object alive. How can I kill the object? What's the Python function/method/whatever to destroy an object?

I'm using Linux and this program works correctly.

But small problem your code:

class CustomWindow(QMainWindow):
    def __init__(self, factorsFile, parent = None):
        QMainWindow.__init__(self, [B]parent[/B])

and

class MainWindow(QMainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self, [B]parent[/B])

The only problem is that it is (terminal output):

[timo@localhost PyQt-converter-2.0]$ python PyQt-converter.pyw 
Segmentation fault

If close program!

Edited 6 Years Ago by -ordi-: n/a

Have you prooved the regular del statement. When object is not referenced it is put for garbage collection.

I'm using Linux and this program works correctly.

[timo@localhost PyQt-converter-2.0]$ python PyQt-converter.pyw 
Segmentation fault

If close program!

I know. But because it doesn't show any errors, not even in Eclipse IDE, I've got no idea why it does that.

tonyjv, "Have you prooved the regular del statement" - what does it mean?

>>> a=(1,2,3)
>>> a
(1, 2, 3)
>>> del a
>>> a

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    a
NameError: name 'a' is not defined
>>>

Hey, I'm debugging your program and find this:

>>> > /home/timo/Downloads/PyQt-converter-2.0/CustomUnits.py(42)__init__()
-> self.factorsFile = factorsFile

Hey, I'm debugging your program and find this:

>>> > /home/timo/Downloads/PyQt-converter-2.0/CustomUnits.py(42)__init__()
-> self.factorsFile = factorsFile

And? Sorry, what is your question? The factorsFile is the xml file I pass to the CustomUnits dialog.

vegaseat,
I need a custom dialog. The QInputDialog doesn't have all the widgets and inputs I need.

tonyjv,
I'll try the 'del'

Edited 6 Years Ago by linuxoidoz: n/a

linuxoidoz,
since i haven't seen this come up yet, if you don't want to destroy and create your dialog each time, have you considered using hide() rather than close(), especially if it's not a modal dialog?
also, i noticed both of your classes are subclassed from QMainWindow ... i haven't tried that myself, maybe CustomWindow should be subclassed from QDialog instead?

Quite the opposite, I do want to destroy it rather then to hide it because by hiding it I need to reset all inputs every time it's hidden. Nothing wrong with that, just doesn't look nice.

And the 'del' crashes it. And it also crashes on every exit without any errors, have no clue why.

Ah, OK. Then it sounds like something in the CustomWindow is referencing something it shouldn't be, so that when it gets garbage collected, it's causing problems. Possibly a circular reference, such as having it and the MainWindow each setting the other as its 'parent' widget, or it and the MainWindow both referencing the same third widget, so that when one is destroyed (taking its children with it), the other then crashes the interpreter when it tries to destroy the shared child. These are just guesses ... without having the entire source of both classes, it's hard to tell.

Also, in case it helps, I can minimally have one QMainWindow kick off instances of the other, with or without explicitly deleting the second:

import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import SIGNAL


class Main1(QtGui.QMainWindow):
  def __init__(self, parent=None):
    QtGui.QMainWindow.__init__(self, parent)
    self.button = QtGui.QPushButton('Create other window', self)
    self.other_window = None
    self.connect(self.button, SIGNAL('clicked()'), self.spawnMain2)
    self.connect(self, SIGNAL('main2closed()'), self.clearMain2)

  def spawnMain2(self):
    self.other_window = Main2()
    self.connect(self.other_window, SIGNAL('closed()'), self.main2Closed)
    self.other_window.show()

  def main2Closed(self):
    self.emit(SIGNAL('main2closed()'))

  def clearMain2(self):
    del self.other_window
    self.other_window = None


class Main2(QtGui.QMainWindow):
  def __init__(self, parent=None):
    QtGui.QMainWindow.__init__(self, parent)
    self.button = QtGui.QPushButton('Quit', self)
    self.connect(self.button, SIGNAL('clicked()'), self.close)


if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  win = Main1()
  win.show()
  sys.exit(app.exec_())
This article has been dead for over six months. Start a new discussion instead.