In my project I need to set a layout in a QtGui::QGraphicsWidget object. Compared to a QWidget (and inherited) object, the 'layout' is set as a Qt property and should accept any object inheriting from the class QGraphicsLayout. Unfortunately when I try to assign a layout I have an error.
You can use the associated setter 'QtGui.QGraphicsWidget::setLayout', but then the returned value for the property 'layout' is still None.
fromPythonQtimportQtCore,QtGuigw=QtGui.QGraphicsWidget()printgw.layout# display Nonegw.setLayout(QtGui.QGraphicsGridLayout())# Ok, but …printgw.layout# … still display None
By digging a little, I also discovered that the property 'QtGui::QGraphicsObject::effect' has the same problem. However, this property has the associated getter 'QtGui::QGraphicsObject::graphicsEffect()' and I am able to retrieve the associated value.
At my level of comprehension, the problem is related to the fact the property 'layout' and 'effect' are associated with object/class which does not inherit from QObject. So they are not registered with the method 'PythonQtPrivate::registerClass()', but with the method 'PythonQtPrivate::registerCPPClass'. Then, these properties are seen by Python as pointer to C++ object.
Is there any way to fix this problem?
Thanks
Arnaud
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Your bug report is correct. There seem to be several issues with PythonQt handling of QProperties that store a pointer (I am not even sure if I think it is a good idea to use
pointers in QProperties, but since it is the Qt API itself, we have to live with it).
For the moment, the best fix I can offer is that you use:
gw.setLayout(...)
and then
gw.layout_()
to get the layout. Note that the _ causes PythonQt to prefer the slot instead of the property, but this has the side-effect that gw.layout will change to a slot after this call (you could consider this a PythonQt bug, but in this case it helps you workaround the problem).
I will also look into fixing the QProperty handling of pointers, but I can't promise when I get time to work on this.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for this patch, this gives me the possibility to get/set the properties QtGui.QGraphicsWidget::layout and 'QtGui.QGraphicsWidget::effect.
However, I discovered than it is not possible to assign a layout (or an effect) if this one is created at the same time than it is assigned. This seems related to the life time of the object. For the 'layout' property, it even crashes Qt.
For example, the next snippet attempts to assign a blur effect, but this one is deleted during its assignation (or seems so).
The worst case is when I do this test with the 'layout' property as it crashes Qt (certainly because the changed layout does not exist anymore).
fromPythonQtimportQtCore,QtGuigw=QtGui.QGraphicsWidget()gw.layout=QtGui.QGraphicsGridLayout()# Crash in QGraphicsWidget::event (type QEvent::LayoutRequest)
However, If I use a temporary variable, this works
fromPythonQtimportQtCore,QtGuigw=QtGui.QGraphicsWidget()ggl=QtGui.QGraphicsGridLayout()gw.layout=ggl# it works!printgw.layout=QGraphicsGridLayout(C++objectat:0x10b968b80)
The reason why the assignation of 'layout' crashed, and not 'effect' might be due to the kind of object. QGraphicsEffect inherits from QObject and not QGraphicsLayout. The later is registered in PythonQt with 'PythonQtPrivate::registerCPPClass', while the former is registered with 'PythonQtPrivate::registerClass()'.
In both case, the use of the setter (i.e. setLayout and setGraphicsEffect) does not help. For the 'effect' property the behaviour is the same, while for the 'layout' property, you have access to an object of the parent class.
fromPythonQtimportQtCore,QtGuigw=QtGui.QGraphicsWidget()gw.setLayout(QtGui.QGraphicsGridLayout())# Seems to work but the stored object is now a QGraphicsLayout and not a QGraphicsGridLayoutprintgw.layout# QGraphicsLayout (C++ object at: 0x10ac33620)
I do not know if this information might help you or not when you would like to implement the handling of a pointer into a QProperty, but at least this is a documented phenomena.
Regards,
Arnaud
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
First of all, thanks for this incredible project!
In my project I need to set a layout in a QtGui::QGraphicsWidget object. Compared to a QWidget (and inherited) object, the 'layout' is set as a Qt property and should accept any object inheriting from the class QGraphicsLayout. Unfortunately when I try to assign a layout I have an error.
You can use the associated setter 'QtGui.QGraphicsWidget::setLayout', but then the returned value for the property 'layout' is still None.
By digging a little, I also discovered that the property 'QtGui::QGraphicsObject::effect' has the same problem. However, this property has the associated getter 'QtGui::QGraphicsObject::graphicsEffect()' and I am able to retrieve the associated value.
At my level of comprehension, the problem is related to the fact the property 'layout' and 'effect' are associated with object/class which does not inherit from QObject. So they are not registered with the method 'PythonQtPrivate::registerClass()', but with the method 'PythonQtPrivate::registerCPPClass'. Then, these properties are seen by Python as pointer to C++ object.
Is there any way to fix this problem?
Thanks
Arnaud
I did not yet have time to look into this, but it's on my todo list.
I will post the results asap.
Your bug report is correct. There seem to be several issues with PythonQt handling of QProperties that store a pointer (I am not even sure if I think it is a good idea to use
pointers in QProperties, but since it is the Qt API itself, we have to live with it).
For the moment, the best fix I can offer is that you use:
gw.setLayout(...)
and then
gw.layout_()
to get the layout. Note that the _ causes PythonQt to prefer the slot instead of the property, but this has the side-effect that gw.layout will change to a slot after this call (you could consider this a PythonQt bug, but in this case it helps you workaround the problem).
I will also look into fixing the QProperty handling of pointers, but I can't promise when I get time to work on this.
The problem is that Qt does not register the meta type for those properties, so their
meta type id is invalid (-1).
This can be fixed by calling the following in your init code:
regards,
Florian
Thanks for this patch, this gives me the possibility to get/set the properties QtGui.QGraphicsWidget::layout and 'QtGui.QGraphicsWidget::effect.
However, I discovered than it is not possible to assign a layout (or an effect) if this one is created at the same time than it is assigned. This seems related to the life time of the object. For the 'layout' property, it even crashes Qt.
For example, the next snippet attempts to assign a blur effect, but this one is deleted during its assignation (or seems so).
However, if I create a temporary variable, this works as expected.
The worst case is when I do this test with the 'layout' property as it crashes Qt (certainly because the changed layout does not exist anymore).
However, If I use a temporary variable, this works
The reason why the assignation of 'layout' crashed, and not 'effect' might be due to the kind of object. QGraphicsEffect inherits from QObject and not QGraphicsLayout. The later is registered in PythonQt with 'PythonQtPrivate::registerCPPClass', while the former is registered with 'PythonQtPrivate::registerClass()'.
In both case, the use of the setter (i.e. setLayout and setGraphicsEffect) does not help. For the 'effect' property the behaviour is the same, while for the 'layout' property, you have access to an object of the parent class.
I do not know if this information might help you or not when you would like to implement the handling of a pointer into a QProperty, but at least this is a documented phenomena.
Regards,
Arnaud