Issue
I am puzzled by a difference of behaviour between Qt5
(PySide2
) and Qt4
(PySide
). I get the impression that Qt5
has a bug but perhaps I do something wrong?
In short: when applying a computed QPainterPath
to a QGraphicsPathItem
(using setPath
), the resulting size of the QGraphicsPathItem
is bigger than the size of the QPainterPath
itself by 1.5 pixels. This makes no sense to me, and with Qt4 the size was exactly the same.
I provide a simple piece of code to reproduce with both PySide and PySide2.
Using PySide:
#!/usr/bin/env python2
from PySide.QtCore import *
from PySide.QtGui import *
class Foo (QGraphicsPathItem):
def __init__(self, parent):
super(Foo, self).__init__()
path = QPainterPath()
path.addRect(0,0,10,10)
print(str(path.boundingRect()))
self.setPath(path)
print(str(self.boundingRect()))
x=Foo(None)
And the result is:
$ python2 ./with_py2.py
PySide.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)
PySide.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)
Same size, as expected. All good.
The exact same code with Qt5:
#!/usr/bin/env python3
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class Foo (QGraphicsPathItem):
def __init__(self, parent):
super(Foo, self).__init__()
path = QPainterPath()
path.addRect(0,0,10,10)
print(str(path.boundingRect()))
self.setPath(path)
print(str(self.boundingRect()))
x=Foo(None)
results in:
$ python3 bug.py
PySide2.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)
PySide2.QtCore.QRectF(-0.500000, -0.500000, 11.000000, 11.000000)
Does anyone see any obvious explanation?
Thanks
Solution
The boundingRect depend on the QPen of the QGraphicsPathItem to calculate it as seen in the source code.
Qt4:
QRectF QGraphicsPathItem::boundingRect() const
{
Q_D(const QGraphicsPathItem);
if (d->boundingRect.isNull()) {
qreal pw = pen().widthF();
if (pw == 0.0)
d->boundingRect = d->path.controlPointRect();
else {
d->boundingRect = shape().controlPointRect();
}
}
return d->boundingRect;
}
QRectF QGraphicsPathItem::boundingRect() const
{
Q_D(const QGraphicsPathItem);
if (d->boundingRect.isNull()) {
qreal pw = pen().style() == Qt::NoPen ? qreal(0) : pen().widthF();
if (pw == 0.0)
d->boundingRect = d->path.controlPointRect();
else {
d->boundingRect = shape().controlPointRect();
}
}
return d->boundingRect;
}
And if you check the Qt docs in both versions you will see that there was a change in the values of the QPen created by default:
- Qt4:
The default pen is a solid black brush with 0 width, square cap style (Qt::SquareCap), and bevel join style (Qt::BevelJoin).
(emphasis mine)
- Qt5:
The default pen is a solid black brush with 1 width, square cap style (Qt::SquareCap), and bevel join style (Qt::BevelJoin).
(emphasis mine)
If you want to observe PySide behavior in PySide2 then set a QPen(Qt::NoPen)
to the QGraphicsPathItem
:
class Foo(QGraphicsPathItem):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setPen(QPen(Qt.NoPen))
path = QPainterPath()
path.addRect(0, 0, 10, 10)
print(str(path.boundingRect()))
self.setPath(path)
print(str(self.boundingRect()))
x = Foo()
Output
PySide2.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)
PySide2.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.