QGraphicsPathItem проблема с вычислением boundingRect
Меня озадачивает разница в поведении между Qt5
(PySide2
) а также Qt4
(PySide
). У меня такое впечатление чтоQt5
есть ошибка, но возможно я что-то делаю не так?
Вкратце: при применении вычисленного QPainterPath
к QGraphicsPathItem
(с помощью setPath
), итоговый размер QGraphicsPathItem
это больше, чем размерQPainterPath
сам на 1,5 пикселя. Для меня это не имеет смысла, и с Qt4 размер был точно таким же.
Я предоставляю простой фрагмент кода для воспроизведения как с PySide, так и с PySide2.
Использование 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)
И вот результат:
$ 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)
Такой же размер, как и ожидалось. Все хорошо.
Точно такой же код с 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)
приводит к:
$ 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)
Кто-нибудь видит очевидное объяснение?
Спасибо
1 ответ
BoundingRect зависит от QPen QGraphicsPathItem, чтобы вычислить его, как показано в исходном коде.
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;
}
И если вы проверите документы Qt в обеих версиях, вы увидите, что произошло изменение значений QPen, созданного по умолчанию:
- Qt4:
Перо по умолчанию - сплошная черная кисть с шириной 0, стилем квадратной шапки (Qt::SquareCap) и стилем соединения скоса (Qt::BevelJoin).
(курсив мой)
- Qt5:
Перо по умолчанию - это сплошная черная кисть с шириной 1, стилем квадратной заглавной буквы (Qt::SquareCap) и стилем соединения скоса (Qt::BevelJoin).
(курсив мой)
Если вы хотите наблюдать за поведением PySide в PySide2, установите QPen(Qt::NoPen)
к 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()
Выход
PySide2.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)
PySide2.QtCore.QRectF(0.000000, 0.000000, 10.000000, 10.000000)