Re: [PyKDE] Lambda function call in connect statement
Phil Thompson wrote: Sorry - I should have noticed this right at the start... The problem is that you are not keeping a reference to the function object that lambda returns - so it is getting garbage collected immediately. The signal is them emitted to an object that no longer exists, hence the segfault. Change the code to be something like... self.lam = lambda s=self,x=num:s.changeTopStruct(x) self.connect( self.top_struct_button, SIGNAL( "clicked()" ), self.lam ) QObject.connect does not keep a reference to the slot object to avoid (potential) hidden circurlar references - but it does mean that you have to manage them yourself. The weakreferences module in Python 2.1 looks interesting - it might offer a more programmer friendly solution. Phil Great! This works. I had a feeling the problem was that I was using lambda incorrectly. -- Aaron J. GinnPhone: 480-814-4463 Motorola SemiCustom SolutionsPager: 877-586-2318 1300 N. Alma School Rd. Fax : 480-814-4463 Chandler, AZ 85226 M/D CH260 mailto:[EMAIL PROTECTED] ___ PyKDE mailing list[EMAIL PROTECTED] http://mats.gmd.de/mailman/listinfo/pykde
Re: [PyKDE] Lambda function call in connect statement
"Aaron J. Ginn" wrote: Phil Thompson wrote: However, I don't like segfaults - send me a small but complete script that demonstrates the problem and I'll take a look. Phil I've attached a script that displays the core dump. I also included the non-lambda version of the connect statement that shows how the pop-up is created prior to the construction of the main window. Sorry - I should have noticed this right at the start... The problem is that you are not keeping a reference to the function object that lambda returns - so it is getting garbage collected immediately. The signal is them emitted to an object that no longer exists, hence the segfault. Change the code to be something like... self.lam = lambda s=self,x=num:s.changeTopStruct(x) self.connect( self.top_struct_button, SIGNAL( "clicked()" ), self.lam ) QObject.connect does not keep a reference to the slot object to avoid (potential) hidden circurlar references - but it does mean that you have to manage them yourself. The weakreferences module in Python 2.1 looks interesting - it might offer a more programmer friendly solution. Phil ___ PyKDE mailing list[EMAIL PROTECTED] http://mats.gmd.de/mailman/listinfo/pykde
Re: [PyKDE] Lambda function call in connect statement
Phil Thompson wrote: As lambda functions are supposed to be "syntactic sugar for a normal function definition" I don't see how using it helps you. Your function wouldn't be executed until the button click anyway. If I write the connect statement without a lambda as follows: -- self.connect( self.top_struct_button, SIGNAL( "clicked()" ), self.changeTopStruct(ver_obj)) -- where changeTopStruct is -- def changeTopStruct(self, obj): """ Pops up an input dialog to prompt user for new top structure name. """ ok_text_tuple = QInputDialog.getText( 'Change Top Structure', 'Enter new Top Structure', None,None) if ok_text_tuple[1] is 1 and ok_text_tuple[0] is not None: obj.set_topstruct( ok_text_tuple[0] ) print obj.get_topstruct() self.top_struct_value.setText( obj.get_topstruct() ) else: return -- The QInputDialog widget in the called function is created before my top QMainWindow that calls the function. As I recall from my work with Tkinter, this is because the call from the connect statement is executed immediately due to the parentheses in the self.changeTopStruct(ver_obj) argument. I thought the only way to get around this is to use a lambda function such as self.connect( self.top_struct_button, SIGNAL( "clicked()" ), lambda s=self,o=ver_obj:s.changeTopStruct(o)) This suppresses the creation of the QInputDialog box until the button is pressed. Is there a better way to do this instead of using a lambda? However, I don't like segfaults - send me a small but complete script that demonstrates the problem and I'll take a look. Phil Will do, but it will take me a little time to put something together. -- Aaron J. GinnPhone: 480-814-4463 Motorola SemiCustom SolutionsPager: 877-586-2318 1300 N. Alma School Rd. Fax : 480-814-4463 Chandler, AZ 85226 M/D CH260 mailto:[EMAIL PROTECTED] ___ PyKDE mailing list[EMAIL PROTECTED] http://mats.gmd.de/mailman/listinfo/pykde
Re: [PyKDE] Lambda function call in connect statement
Phil Thompson wrote: However, I don't like segfaults - send me a small but complete script that demonstrates the problem and I'll take a look. Phil I've attached a script that displays the core dump. I also included the non-lambda version of the connect statement that shows how the pop-up is created prior to the construction of the main window. Aaron -- Aaron J. GinnPhone: 480-814-4463 Motorola SemiCustom SolutionsPager: 877-586-2318 1300 N. Alma School Rd. Fax : 480-814-4463 Chandler, AZ 85226 M/D CH260 mailto:[EMAIL PROTECTED] #!/usr/bin/env python from qt import * import os import sys class Lambda(QMainWindow): def __init__(self): num = 1 QMainWindow.__init__(self) # Build the menubar. mb = self.menuBar() file_menu = QPopupMenu(self) mb.insertItem('File',file_menu) help_menu = QPopupMenu(self) mb.insertItem('Help',help_menu) # Build the middle VBox where widgets will go. self.vb = QVBox( self ) self.setCentralWidget( self.vb ) self.vb.setFrameStyle(QFrame.StyledPanel|QFrame.Raised) self.vb.setMargin(1) self.vb.setLineWidth(2) self.top_struct_hb = QHBox( self.vb ) self.top_struct_value = QLabel( 'Test', self.top_struct_hb) self.top_struct_button = QPushButton('Click me', self.top_struct_hb) # --- # Uncomment these lines to see the effect without the lambda # statement. The QInputDialog command will be created before # the main window is created. # --- ##self.connect( self.top_struct_button, SIGNAL( "clicked()" ), ## self.changeTopStruct(num)) self.connect( self.top_struct_button, SIGNAL( "clicked()" ), lambda s=self,x=num:s.changeTopStruct(x)) # Build the status bar. sb = self.statusBar() return def changeTopStruct(self, a_num): """ Pops up an input dialog to prompt user for new top structure name. """ text_tuple = QInputDialog.getText( 'Test', 'Test', None, None ) if text_tuple[1] is 1 and text_tuple[0] is not None: print 'Ok' else: print 'Cancel' return # main() a = QApplication( sys.argv ) a_lambda = Lambda() a.setMainWidget( a_lambda ) a_lambda.show() a.exec_loop()