[PyQt] Bug in QTableView.setModel()
Brian Kelley
kelley at eyesopen.com
Tue Jan 8 14:25:35 GMT 2008
On Jan 8, 2008, at 7:12 AM, Aaron Digulla wrote:
> Quoting Phil Thompson <phil at riverbankcomputing.co.uk>:
>
>> I'm happy to consider ways to make this more obvious (even if it's
>> just a
>> better FAQ), but I'm not happy about departing from the Qt API and
>> introducing inconsistencies in fundamental behaviour.
>
> Then let me put it this way: If I wanted to care about who calls the
> dtor, I'd be using C++ and not Python. ;-)
>
> As a Python developer, I expect PyQt to behave like python code: As
> long as anyone (my code, PyQr or Qt) still has references to some
> object, the dtor must not be called, no matter what and PyQt as a
> *python* wrapper for Qt should follow the Python rules, not the Qt
> rules, especially not in a case where there is no conflict.
So you have never written to a closed pipe? This is an equivalent
situtation, you have a python reference to a destructed (or closed in
this case) object.
Trust me, I know what you are saying here, but I agree with Phil that
in this case it is difficult to have your cake and eat it too. When
wrapping C++ objects in python in any complicated enough system, be it
using sip or swig you really have no choice when the C++ destructor is
called. Consider a simple callback:
def callback():
f = QtGui.QFrame()
f.show()
button = QtGui.QPushButton("clickme")
button.connect(QtCore.SIGNAL("clicked()"), callback)
In this case "f" is created and immediately goes out of scope in the
function, and yet the QFrame is shown and not deleted. This is
because "f" now belongs to the Qt event loop. This, in itself, should
show why you can't control when constructors and destructors are called.
or suppose you hang onto a widget ( say b = QtGui.QPushButton ) that
lives in a widget that the user closes and Qt deletes. b is now a
dangling reference to a deleted C++ object! Trust me, you cannot
prevent this and you probably really don't want to, anyway.
The reason that the model is different when using QModel is that you
*MUST* control when the object is destructed because it is shared.
Let's say that you make this change in setModel but you use a model
created in C++ by some other mechanism (yes, PyQt doesn't care where
the model comes from, python or C++). By making this change you may
destruct the model accidentally but because it came from C++
somewhere, other C++ objects know nothing about Python's garbage
collection and this may lead to nasty, nasty problems.
So what is Phil to do? The best solution is to be consistent as
possible with the Qt API since that is where these behaviors are
documented.
The other option is to write a GUI completely with python, or at least
with python in mind and you are most welcome to do that or you can
just make a subclass yourself (you essentially did this already)
class MyTable(QtGui.QTableView):
def setModel(self, m):
self.model = m
QtGui.QTableView.setModel(m)
There, now you have the behavior you want, and it is even explicitly
and not implicitly set which is quite pythonic.
Brian
More information about the PyQt
mailing list