pythonqt
pythonqt copied to clipboard
super() does not work for Qt classes
I just want to share some insights into this issue, I currently have no intention to fix the issue, as that would be somewhat complicated.
This is an example of what does not work:
from PythonQt.QtGui import QDoubleValidator
class MyFunnyValidator(QDoubleValidator):
def setRange(self, minimum, maximum, decimals):
super().setRange(minimum, maximum, decimals+1)
The problem boils down to the fact that the method lookup of super() directly accesses the internal tp_dict member of the super classes, which is only filled to an absolute minimum by PythonQt (for performance reasons). Everything else is delivered through tp_getattro calls, but this does not work for super.
I discussed with Florian Link what would have to be done to fill the tp_dict.
- This would probably need to happen in PythonQtInstanceWrapper_init the first time an instance of the class is created.
- One could have a look at PythonQtClassWrapper_getattro how this is done, where the __dict__ member is dynamically filled.
- But one would have to have in mind that QObject class wrappers can get updated methods when, e.g., the Qt bindings are loaded, so the class tp_dict would have to be updated then or at least flushed.
- There might be other unforeseen consequences.
We both agreed that this change is somewhat tricky and probably currently not worthwhile.
@usiems Is there any known workaround on the python-code side for this?
When taking the above example, you can always do
QDoubleValidator.setRange(self, minimum, maximum, decimals+1)
instead.
I had a problem yesterday with sizeHint
from QWidget. I was aware of the variant you described for QDoubleValidator
but I had problems with a property.
My Class is a simple Code block which should resize the content of the text.
Here is a rough version (not working 100% for the resize).
class Code(QPlainTextEdit):
def __init__(self, parent=None):
super(Code, self).__init__(parent)
def heightForWidth(self):
# some calc here
return 30
def sizeHint(self):
original_hint = super(QWidget, self).sizeHint # does not work as described in the description of the issue
original_hint = QPlainTextEdit.sizeHint(self) # exception: QSize object no callable
original_hint = QPlainTextEdit(self).sizeHint # the only which seems to work
return QSize(original_hint.width(), self.heightForWidth(original_hint.width()))
original_hint = QPlainTextEdit(self).sizeHint # the only which seems to work
was the only version which was working or in other words don't throw an exception. It creates a second QPlainTextEdit as far as I can see.
What iss the correct way to get a property?
QPlainTextEdit(self).sizeHint
is probably not what you want; this should create a new QPlainTextEdit with your instance as the parent.
QPlainTextEdit.sizeHint(self)
would be the correct solution, but PythonQt seems to treat sizeHint like a property, though only instances have properties, not their classes. I wonder which QSize is returned here. Anyway, I consider this a bug, but no promises by me if and when this will be fixed.
So, I believe there is currently no way to do this correctly for properties.
@usiems Thanks for looking into this. QPlainTextEdit.sizeHint(self)
was also my logical answer, good to know that this should be right. I'm not on the latest PythonQt version, so I will migrate and will try again.