QGraphicsPathItem проблема с вычислением boundingRect - PullRequest
1 голос
/ 06 ноября 2019

Я озадачен разницей в поведении между 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 Ответ

2 голосов
/ 06 ноября 2019

Значение 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;
}

Qt5

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, созданного по умолчанию:

Ручка по умолчанию представляет собой сплошную черную кисть с 0 шириной , стилем квадратной крышки (Qt :: SquareCap) и стилем скоса (Qt :: BevelJoin).

(выделено мной)

Ручкой по умолчанию являетсясплошная черная кисть с шириной 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)
...