PySide QListWidget of selection with scriptJob

502 views
Skip to first unread message

Drew Bradford

unread,
Oct 7, 2013, 8:40:01 PM10/7/13
to python_in...@googlegroups.com
Hello Everyone,

I am trying to get a QListWidget to update with a users current selection. So far it is working very temperamentally, and seems to throw and error whenever it feels like it. I think the problem originates with cmds.scriptJob. I am using the scriptJob to monitor when the user selection changes. I have been trying to set the scriptJob's parent to the window so that when I close the window the script job gets deleted. I'm hoping that helps alleviate the problem. I am new to PySide and there doesn't seem to be something as simple as window = cmds.window().

Any help would be fantastic! It almost seems as if self is referencing the window in PySide?

Check out my code here: 

# Error: Internal C++ object (PySide.QtGui.QListWidget) already deleted.
# Traceback (most recent call last):
#   File "/Volumes/Macintosh HD/Users/drew/Library/Preferences/Autodesk/maya/2014-x64/scripts/dbTools/selObjectsQListWidget.py", line 55, in populateList
#     self.objectsList.clear()
#   File "/Volumes/Macintosh HD/Users/drew/Library/Preferences/Autodesk/maya/2014-x64/scripts/dbTools/selObjectsQListWidget.py", line 55, in populateList
#     self.objectsList.clear()
# RuntimeError: Internal C++ object (PySide.QtGui.QListWidget) already deleted. # 


Joe Weidenbach

unread,
Oct 7, 2013, 11:30:14 PM10/7/13
to python_in...@googlegroups.com
I believe, from my limited PyQt knowledge, that the QListWidget is behaving badly due to the order of operations in creating it.  Specifically, you are setting the list to be parented to self, but you are not setting your widget's layout to be the layout you're adding the list to.  Try adding self.setLayout(self.homeLayout) to the end of createLayouts, like so:

def createLayouts(self):

	#Home Layout
	self.homeLayout = QtGui.QGridLayout(self)
	self.homeLayout.setObjectName("homeLayout")
	self.homeLayout.addWidget(self.objectsList, 0, 0, 1, 1)
	self.setLayout(self.homeLayout)

With that said, I didn't get any errors from the code once I removed the pymel search for an existing window from the createWindow() function.

A possible replacement (which is on this list from a few days ago) is this:

	global renamerWindow
	try:
		renamerWindow.deleteLater()
	except:
		pass
	renamerWindow = RenameWindow(parent=mayaPythonMainWindow())
Seems to work fine that way, but it could just be me...

Joe
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/87239f13-c764-4167-8809-d32b24f33363%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Joe Weidenbach

unread,
Oct 7, 2013, 11:35:29 PM10/7/13
to python_in...@googlegroups.com
Oh, one more quick thought:

It's best to set parent=self on the scriptjob.  Otherwise, the scriptjob will continue running once the window is closed.  That could account for your error.

Joe Weidenbach

unread,
Oct 7, 2013, 11:41:00 PM10/7/13
to python_in...@googlegroups.com
Whoops, should be better at reading the whole post :). Setting parent=self when you call the scriptjob should help, in the way you mentioned.  like I said, the main error I got when I ran it was from pymel--and that could easily just be a messed up path for me (seems like all of my versions except for 2012 go into an endless loop of reloading plugins when I call pymel).

Justin Israel

unread,
Oct 8, 2013, 12:33:40 AM10/8/13
to python_in...@googlegroups.com
The way you are setting up the layout actually looks fine to me. Passing a widget to the constructor of the layout is effectively the same as called widget.setLayout(layout) later, so it would be redundant to add the setLayout call.

I do agree that using the global to store the single window instance is a good alternative to having to mix your code with PyMel or the cmds module if you don't really need them otherwise. The only problem you might run into is if you dynamically reload the module, which would cause you to lose the reference to the global. A 3rd approach is to just check for the object using Qt:

win = mayaPythonMainWindow()
existing = win.findChild(QtGui.QWidget, "renamerWindow")
if existing:
    existing.deleteLater()

Really the only thing I see as probably the issue is what Joe pointed out, regarding the script job not getting cleaned up if it hasn't fired before, but the window is deleted. I am not 100% sure but does the scriptjob parent argument expect a Maya UI path and not a Qt widget? If so, you can't pass self. There are a couple approach to handling this as well. One way is to look up the UI path of your window and pass that to parent:

ptr = long(shiboken.getCppPointer(self)[0])
name = mui.MQtUtil.fullName(ptr)
scriptJobNum = cmds.scriptJob(event = ["SelectionChanged", self.populateList], parent=name)

Another way might be to save the scriptJobNum, and then kill the scriptJob in your __del__ method of your class.




Drew Bradford

unread,
Oct 8, 2013, 2:26:15 PM10/8/13
to python_in...@googlegroups.com
Joe and Justin,
Woo!! Thanks very much you have solved the issue. Your explanations were extremely helpful.

Cheers,
Drew
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages