Il giorno ven, 21/01/2011 alle 22.01 +0100, Erik Janssens ha scritto:
> Hello Nicola,
> 
> I'm not sure what happens when you reset the parent of a widget to None,
> (wether it then transfers ownership back to python).

it works

> 
> If you get that run-time error, this means that qt deleted the widget, this
> random effect might have been triggered by the garbage collector.
> 

I cannot reproduce the error systematically it never happened during my
tests, a customer reported to me this error, I added the try except
statment and noone reported any problem

> you can verify this by disabling the garbage collector and see if
> it still happens :
> 
> import gc
> gc.disable()
> 
> I'm don't know if this trick with reparenting works, but it looks like
> a good trick to have speedups ??

attacched is an updated sample with a time.sleep in __init__, so when
the dialog is loaded from the cache the difference is noticeable.

if I understand your article
(http://downloads.conceptive.be/downloads/camelot/doc/sphinx/build/advanced/development.html)
 my sample should not work, I'm setting the parent of a qt object to None, so 
qt should delete it, and I'm keeping a reference to the python object (this 
seems the opposite of what you suggets). Please play with the sample, for 
example you can:

- click on "Open dialog", the first time you'll wait about 5 seconds
- when you close the dialog it's parent is setted to None, and the
global object is populated
- click "Change widget", and click "Open dialog" again (from a different
widget), this time the dialog is loaded from the cache
- you can repeat the sequence, or try any other order

this works, but probably it should not work ...

Nicola

> 
> Erik
> 
> On Fri, Jan 21, 2011 at 10:21 AM, Mailing List SVR
> <li...@svrinformatica.it> wrote:
> > Hi Erik,
> >
> > attacched is a small sample of what I'm doing in my app, I have a dialog
> > that require some time to open, to speed up the things I store it in a
> > global object and use this global object to reopen the dialog,
> >
> > this seems to work, I'm reusing the same dialog from different central
> > widget, some times (I'm unable to reproduce) I see in the logs:
> >
> > RuntimeError: underlying C/C++ object has been deleted
> >
> > so I added a try except when I open the dialog, until today noone
> > reported segfault, what do you think about this usage?
> >
> > thanks
> > Nicola
> >
> > Il giorno ven, 21/01/2011 alle 08.47 +0100, Erik Janssens ha scritto:
> >> Hi,
> >>
> >> I wrote some general documentation around these
> >> issues, with regard to Camelot development, but
> >> it might be of use to others as well :
> >>
> >> http://downloads.conceptive.be/downloads/camelot/doc/sphinx/build/advanced/development.html
> >>
> >> all remarks/corrections are welcome.
> >>
> >> Regards,
> >>
> >> Erik
> >>
> >> On Thu, 2011-01-20 at 10:22 +0100, Mailing List SVR wrote:
> >> > Ok, in a my pyqt app (I'm still using pyqt-4.7.x), I have a dialog that
> >> > require much time to open so I keep a reference to it in a app global
> >> > variable and I use this reference to reopen the dialog after the first
> >> > time. This seems to work and the dialog open much quicker, however in
> >> > some undeterminated cases I get:
> >> >
> >> > RuntimeError: underlying C/C++ object has been deleted
> >> >
> >> > when I get this error I recreate the dialog and update the global
> >> > reference,
> >> >
> >> > can you please explain the right way to keep a reference in python to a
> >> > qt object?
> >> >
> >> > thanks
> >> > NIcola
> >> >
> >> >
> >> > Il giorno mer, 19/01/2011 alle 23.47 +0100, Erik Janssens ha scritto:
> >> > > there was a change in sip/pyqt from 4.8.1 to 4.8.2 regarding
> >> > > the detection of objects deleted by qt but still referenced in
> >> > > python (which is the case here).  in 4.8.1 sip/pyqt tried to
> >> > > detect this to avoid segfaults.  this detection however brought
> >> > > other issues with it, therefor the detection was turned off again
> >> > > in 4.8.2
> >> > >
> >> > > the solution is not to keep references in python of objects
> >> > > owned by qt when they might get deleted.
> >> > >
> >> > > On Wed, Jan 19, 2011 at 12:36 PM, Mailing List SVR
> >> > > <li...@svrinformatica.it> wrote:
> >> > > > I can confirm the segfault:
> >> > > >
> >> > > > - linux, kernel 2.6.36
> >> > > > - python 2.7.1
> >> > > > - pyqt 4.8.2
> >> > > > - qt 4.7.1
> >> > > >
> >> > > > works fine with PySide,
> >> > > >
> >> > > > Nicola
> >> > > >
> >> > > >
> >> > > > Il giorno mer, 19/01/2011 alle 08.36 +0100, Vicent Mas ha scritto:
> >> > > >> 2011/1/18 Nick Gaens <m...@nickgaens.com>:
> >> > > >> > - Win7 64bit
> >> > > >> > - Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 
> >> > > >> > bit
> >> > > >> > (Intel)] on win32
> >> > > >> > - Qt v4.7.0
> >> > > >> > - PyQt GPL v4.8.1 for Python v2.6
> >> > > >> > Result: no crashes, works like a charm..
> >> > > >> >
> >> > > >>
> >> > > >> Hi,
> >> > > >>
> >> > > >> I get the crash also on Windows Vista 32bit (again Python 2.6 and 
> >> > > >> PyQt 4.8.2)
> >> > > >>
> >> > > >> Vicent
> >> > > >>
> >> > > >
> >> > > > _______________________________________________
> >> > > > PyQt mailing list    PyQt@riverbankcomputing.com
> >> > > > http://www.riverbankcomputing.com/mailman/listinfo/pyqt
> >> > > >
> >> > > _______________________________________________
> >> > > PyQt mailing list    PyQt@riverbankcomputing.com
> >> > > http://www.riverbankcomputing.com/mailman/listinfo/pyqt
> >> >
> >>
> >>
> >
> _______________________________________________
> PyQt mailing list    PyQt@riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui, QtCore
import time

class AppGlobal(object):
	global_dlg=None

app_global=AppGlobal()	

class TestDialog(QtGui.QDialog):
	def __init__(self,parent=None):
		super(TestDialog,self).__init__(parent)
		time.sleep(5)
		self.setWindowTitle('Reference Dialog')
		self.setGeometry(200, 200, 150, 120)
		self.test_button = QtGui.QPushButton('Close dialog', self)
		self.connect(self.test_button, QtCore.SIGNAL('clicked()'),self.accept)
		
	def onClose(self):
		print self.parent()
		if app_global.global_dlg is None:
			print 'keep a dialoog reference in app_global'
			app_global.global_dlg=self
		self.setParent(None)
	
	def accept(self):
		self.onClose()
		QtGui.QDialog.accept(self)
	
	def reject(self):
		self.onClose()
		QtGui.QDialog.reject(self)
	

class TestWidget(QtGui.QWidget):
	def __init__(self, parent=None):
		QtGui.QWidget.__init__(self, parent)
		self.setGeometry(300, 300, 250, 150)
		self.test_button = QtGui.QPushButton('Open dialog', self)
		self.test_button.setGeometry(10, 10, 200, 35)
		self.test_button1 = QtGui.QPushButton('Change widget', self)
		self.test_button1.setGeometry(10, 60, 200, 35)
		self.connect(self.test_button, QtCore.SIGNAL('clicked()'),self.onClick)
		self.connect(self.test_button1, QtCore.SIGNAL('clicked()'),self.onClick1)
    
	def onClick(self):
		if not app_global.global_dlg:
			print 'new dialog created'
			dlg=TestDialog(self)
			dlg.exec_()
		else:
			try:
				print "open saved dialog"
				#app_global.global_dlg.setParent(self)
				app_global.global_dlg.exec_()	
			except Exception,e:
				print e
				app_global.global_dlg=None
				dlg=TestDialog(self)
				dlg.exec_()
      		
	def onClick1(self):
		#print 'change widget from TestWidget'
		self.parent().setCentralWidget(AnotherWidget())

      
class AnotherWidget(QtGui.QWidget):
	def __init__(self, parent=None):
		QtGui.QWidget.__init__(self, parent)
		self.setGeometry(300, 300, 250, 150)
		self.test_button = QtGui.QPushButton('back', self)
		self.test_button.setGeometry(10, 60, 200, 35)
		self.test_button1 = QtGui.QPushButton('Open Dialog', self)
		self.test_button1.setGeometry(10, 10, 200, 35)
		self.connect(self.test_button, QtCore.SIGNAL('clicked()'),self.onClick)
		self.connect(self.test_button1, QtCore.SIGNAL('clicked()'),self.onClick1)
     
	def onClick(self):
		#print 'change widget from AnotherWidget'
		w=TestWidget()
		self.parent().setCentralWidget(w)
	
	def onClick1(self):
		if not app_global.global_dlg:
			print 'new dialog created'
			dlg=TestDialog(self)
			dlg.exec_()
		else:
			try:
				print "open saved dialog"
				#app_global.global_dlg.setParent(self)
				app_global.global_dlg.exec_()	
			except Exception,e:
				print e
				app_global.global_dlg=None
				dlg=TestDialog(self)
				dlg.exec_()
        
  

class MainApp(QtGui.QMainWindow):
	def __init__(self, parent=None):
		QtGui.QMainWindow.__init__(self, parent)
		self.setGeometry(300, 300, 250, 150)
		self.setWindowTitle('Reference Demo')
		t=TestWidget()
		self.setCentralWidget(t)

app = QtGui.QApplication(sys.argv)
m = MainApp()
m.show()
sys.exit(app.exec_())

_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to