I am working on a project where a function is throwing a wx.pyDeadObject Error because of a delayed task.
I've read that in wx you can check if the c++ object still exsists by running if self:, however this no longer works in wxPython 3.0.2. using wx 3.
I've modified the function to the following:
def SetData(self, delayedResult):
if not self or not self.list:
return
data = []
torrents = delayedResult.get()
for torrent in torrents:
data.append((torrent.infohash, [torrent.name], torrent, ThumbnailListItemNoTorrent))
self_exist = True
list_exists = True
if not self:
self_exist = False
if not self.list:
list_exists = False
try:
self.list.SetData(data)
self.list.SetupScrolling()
except wx.PyDeadObjectError:
print "Self existed: %s and self.list existed: %s" % (self_exist, list_exists)
It already passes the first if statement, but since the delayedResutlt.get() is blocking I added the additional try except (I also tried duplicating that if statement at the start of the function, but that didn't work).
When running one of the unit tests I got Self existed: True and self.list existed: True which confirmed my suspicions. The documentation of 3.0.3 says this should be present.
How can you test if the c++ part of a wx object has been deleted in wxPython?
Turns out that you first have to wx.Yield() after having called Destroy() or something alike, in contrast to wx 2.8. The events then get processed and destroyed.
In all cases, using bool(object) will evaluate to True or False depending on if the object is still active.
To know if c++ object of a wxPython window still exists, you must use
self.__nonzero__()
A more detailed answer at:
Defining a wx.Panel destructor in wxpython
and also documentation from wxPython and the PyDeadObject error at:
https://wxpython.org/Phoenix/docs/html/MigrationGuide.html
Related
I'm trying to add some popular plugins to GIMP (version 2.99.10), but when I launch GIMP, I get errors like the following:
AttributeError: 'SuperResolution' object has no attribute 'set_translation_domain'
SuperResolution is a subclass of Gimp.PlugIn.
I've only installed GIMP recently, so I'm guessing there's some sort of path / scope issue that's causing python not to be able to see the inherited set_translation_domain attribute, but I don't exactly know what the problem would be.
Any ideas?
In superresolution.py replace this:
def do_query_procedures(self):
self.set_translation_domain(
"gimp30-python", Gio.file_new_for_path(Gimp.locale_directory())
)
return ["superresolution"]
To this:
def do_query_procedures(self):
return ["superresolution"]
def do_set_i18n(self, procname):
return True, 'gimp30-python', None
That happens because they changed how localization works in the recent builds of GIMP (2.99.10 - 2.99.13). Here is one of their internal plugins foggify to compare.
I am working on a mini GUI project , I am currently struggling to figure out how to get selected value from the list and then return that value to the main function so that I can use that value in somewhere else . Can someone help me please !!!!
####
self.device_list_store = gtk.ListStore(str,str,str,str,str)
for device in self.get_dev_list():
self.device_list_store.append(list(device))
device_list_treeview = gtk.TreeView(self.device_list_store)
selected_row = device_list_treeview.get_selection()
selected_row.connect("changed",self.item_selected)
####
def item_selected(self,selection):
model,row = selection.get_selected()
if row is not None:
selected_device = model[row][0]
at the moment ,the item_selected function is not returning anything , I want to return selected_device back to the main function so I can use it in other functions as well .
EDIT: I've edited code above to remove formatting errors #jcoppens
As you can see in the documentation, the item_selected function is called with one parameter, tree_selection. But if you define the function inside a class, it requires the self parameter too, which is normally added automatically. In your (confusing) example, there is no class defined, so I suspect the problem is your program which is incomplete.
Also, I suspect you don't want device_list_treeview = gtk.T... in the for loop:
for device in self.get_dev_list():
self.device_list_store.append(list(device))
device_list_treeview = gtk.TreeView(self.device_list_store)
And I suspect you want selected_device = mod... indented below the if:
if row is not None:
selected_device = model[row][0]
Please convert your example in a complete program, and formatted correctly.
BTW: item_selected is not a good name for the signal handler. It is also called if the item is unselected (which is why the signal is called 'changed')!
And important: Even though you should first read the basic Python tutorials and Gtk tutorials, you should then consider using lazka's excellent reference for all the Python APIs. There's a link on the page to download it completely and have it at hand in your computer.
I have a wxPython GUI with a very large grid. I am using similar code to the GridHugeTable.py example from the wxPython demo -- i.e., using PyGridTableBase to make a virtual grid.
I am running into trouble when I try to interactively add columns to this grid, however.
Calling AppendCols(1) results in this error:
wx._core.PyAssertionError: C++ assertion "Assert failure" failed at /Users/vagrant/pisi-64bit/tmp/wxPython-3.0.2.0-3/work/wxPython-src-3.0.2.0/src/generic/grid.cpp(1129) in AppendCols():
Called grid table class function AppendCols but your derived table class does not override this function
But if I try to overwrite AppendCols in my table class, the application just hangs indefinitely and never resolves. It hangs even if there is actually nothing in my custom AppendCols method at all...
class HugeTable(gridlib.PyGridTableBase):
"""
Table class for virtual grid
"""
def __init__(self, log, num_rows, num_cols):
gridlib.PyGridTableBase.__init__(self)
def AppendCols(self, *args):
pass
I've been able to overwrite other methods successfully, (setValue, getValue, getColLabelValue, etc.), so I'm not sure what is different here.
Update:
I returned to this problem after a while away. I no longer get the wx.__core.PyAssertionError. However, I still can't get my custom AppendCols method to work. I can't figure out what to put in AppendCols to make a new column actually show up.
I'm not sure how to look in the source code -- none of the Python documentation seems to have what I'm looking for, so maybe I need to go digging in wxWidgets? The documentation hasn't helped: https://wiki.wxpython.org/wxPyGridTableBase.
The clue I needed is in the the demo code for custom table.
So, this code works (leaving out my custom logic and just including the bare bones):
def AppendCols(self, *args):
msg = gridlib.GridTableMessage(self, # The table
gridlib.GRIDTABLE_NOTIFY_COLS_APPENDED, # what we did to it
1) # how many
self.GetView().ProcessTableMessage(msg)
return True
Same exact problem as this: Connecting QTableView selectionChanged signal produces segfault with PyQt
I have a QListView, and I want to call a function when an item is selected:
self.server_list = QtGui.QListView(self.main_widget)
self.server_list_model = QtGui.QStandardItemModel()
self.server_list.setModel(self.server_list_model)
self.server_list.selectionModel().selectionChanged.connect(self.server_changed)
But, when it reaches the last line, where I'm using the selection model, the app crashes. Not with a traceback, but with a "appname has stopped working" from Windows. I'm pretty sure that's a segfault.
BUT, when I use PyQt4 it works fine. I'm using PySide because it's LGPL.
Yes, I'm on the latest versions of everything (PySide: 1.2.1, Python 2.7.5, Qt 4.8.5).
Can anyone help me with this?
Try holding a reference to the selection model for the lifetime of the selection model. That worked for me with a similar problem (seg fault when connecting to currentChanged event on a table views selection model).
self.server_list = QtGui.QListView(self.main_widget)
self.server_list_model = QtGui.QStandardItemModel()
self.server_list.setModel(self.server_list_model)
self.server_list_selection_model = self.server_list.selectionModel() # workaround
self.server_list_selection_model.selectionChanged.connect(self.server_changed)
For some reason, the last two lines work, while combining them into one command throws an error.
Same problem here: http://permalink.gmane.org/gmane.comp.lib.qt.pyside.devel/541
And I also answered: http://permalink.gmane.org/gmane.comp.lib.qt.pyside.devel/542
I suspect what happens is:
self.server_list # local object
.selectionModel() # call C++ method, wraps C++ object in Python object
.selectionChanged # get property of object
# selection model is now out of scope and gets garbage collected
.connect(...) # OOPS! ...operating on object that no longer exists!
On Mac OS X the trackpad has support for several gestures, one is the two fingered swipe to scroll up, down, left, or right on a page. wxPython has a panel to help create scrolled widgets wx.lib.scrolledpanel. However it does not have support for gestures which is a real pain.
I have tried to modify the NSView, as it is done if it were a normal Objective C application, however the NSEvents use methods (touchesBeganWithEvent:, etc) that are subclassed to be used as a notification and handling of an event. This is unlike the Bind calls in wxPython. This would be fine however if Objective C allowed monkey patching... eg
def handleTouchBegin(event):
print "Hey a touch event has begun!"
view.touchBeganWithEvent_ = handleTouchBegin
but as you can guess PyObj C errors (because Objective C doesn't support monkey patching or not in any clean and nice fashion) and I get the following error
TypeError: cannot change a method
Ok well I could do what apple says and subclass it, but the object is already created, so how can I still capture the events. Of course there is also
NSEvent addGlobalMonitorForEventsMatchingMask:
and
NSEvent addLocalMonitorForEventsMatchingMask:
but those also disappoint in that they either don't even deal with the application (global deals with all the others) or doesn't deal with a single NSView's events (or does it and I am misinformed).
So how should I do this? Am I missing another option, I know I read something about NSResponder but from what I gathered that is what NSView is, an event responder and you don't add one to a NSView.
Are there observers like in QTKit such as for monitoring the load state changing ( https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/QTKitApplicationProgrammingGuide/AnatomyoftheQTKFramework/AnatomyoftheQTKFramework.html#//apple_ref/doc/uid/TP40008156-CH109-SW11 )?
ObjC doesn't support Python-style monkeypatching… but it does support some similar features like method swizzling, class posing, category interposition, etc. And PyObjC can do all of those things.
Off the top of my head, swizzling from PyObjC should look something like this:
def swizzle(cls, sel, func):
oldimp = cls.instanceMethodForSelector_(sel)
def wrapper(self, *args, **kwargs):
return func(self, oldimp, *args, **kwargs)
newmethod = objc.selector(wrapper,
selector=oldimp.selector, signature=oldimp.signature)
objc.classAddMethod(cls, sel, newmethod)
return wrapper