Qt4 到 Qt5:QPainter::drawPixmapFragments() 有 5 个参数 - 如何解决?

Qt4 to Qt5: QPainter::drawPixmapFragments() with 5 arguments - how to solve?

Qt 4.8 (4.8.6) 有一个带有 5 个参数的 QPainter::drawPixmapFragments() 重载函数:

void drawPixmapFragments(const QRectF *targetRects, const QRectF *sourceRects, int fragmentCount,
                         const QPixmap &pixmap, PixmapFragmentHints hints = 0);

Qt 5 (5.4.1) 没有这样的函数,它只有一个(与 Qt 4.8 相同)有 4 个参数:

void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
                         const QPixmap &pixmap, PixmapFragmentHints hints = 0);

我在 wiki.qt.io 中搜索过,这里在 Whosebug 和其他几个地方,但没有答案如何将它从 Qt 4.8 移植到 Qt 5。

怎么做?

UPD 我从 Qt 4.8.6 源代码 (qpainter.cpp) 中获取了实现,并简单地将其转换为将指向 QPainter 的指针作为第一个参数:

namespace oldqt
{
    void drawPixmapFragments(QPainter *painter, const QRectF *targetRects, const QRectF *sourceRects, int fragmentCount,
        const QPixmap &pixmap, QPainter::PixmapFragmentHints hints)
    {
        // Q_D(QPainter); 

        if (/* !d->engine || */ pixmap.isNull())
            return;

    #ifndef QT_NO_DEBUG
        if (sourceRects) {
            for (int i = 0; i < fragmentCount; ++i) {
                QRectF sourceRect = sourceRects[i];
                if (!(QRectF(pixmap.rect()).contains(sourceRect)))
                    qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
            }
        }
    #endif

    // if (d->engine->isExtended()) {
    //              d->extended->drawPixmapFragments(targetRects, sourceRects, fragmentCount, pixmap, hints);
    //          }
    //          else {
            if (sourceRects) {
                for (int i = 0; i < fragmentCount; ++i)
                    painter->drawPixmap(targetRects[i], pixmap, sourceRects[i]);
            }
            else {
                QRectF sourceRect = pixmap.rect();
                for (int i = 0; i < fragmentCount; ++i)
                    painter->drawPixmap(targetRects[i], pixmap, sourceRect);
            }
    //          }

    }
}

但是我注释掉了一些行。 Q_D(QPainter) 以某种方式从 d_func 定义了 d,我如何从 *painter 中获取它?或者这是不可能的? 可能还有其他解决方案?

UPD2 我的旧代码示例:

class ButtonSelector:public QGraphicsObject
// ...

void ButtonSelector::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    //painter->drawPixmap(m_backGnd.rect(), m_backGnd);
    QRectF rectSrc = QRectF(m_backGnd.rect());
    QRectF rectTrg = boundingRect();
    painter->drawPixmapFragments(&rectTrg,&rectSrc,1,m_backGnd, QPainter::OpaqueHint);
    // I've change it to this call:
    // oldqt::drawPixmapFragments(painter, &rectTrg, &rectSrc, 1, m_backGnd, QPainter::OpaqueHint);
    // where oldqt::drawPixmapFragments is function from above

    // ... some other code unrelated to the question
}

原则上是可以的。代码中有什么不正确的地方?

解决方案 基于 by @amartel:

void drawPixmapFragments(QPainter *painter, const QRectF *targetRects, const QRectF *sourceRects, int fragmentCount,
    const QPixmap &pixmap, QPainter::PixmapFragmentHints hints)
{
    for (int i = 0; i < fragmentCount; ++i) {
        QRectF sourceRect = (sourceRects) ? sourceRects[i] : pixmap.rect();

        QPainter::PixmapFragment pixmapFragment =
            QPainter::PixmapFragment::create(
                targetRects[i].center(),
                sourceRects[i],
                targetRects[i].width() / sourceRect.width(),
                targetRects[i].height() / sourceRect.height()
            );

        painter->drawPixmapFragments(&pixmapFragment, 1, pixmap, hints);
    }
}

文档清楚地说明了如何 "adjust" 转换:

取自:http://qt.apidoc.info/5.1.1/qtgui/qpainter-pixmapfragment.html

The sourceLeft, sourceTop, width and height variables are used as a source rectangle within the pixmap passed into the QPainter::drawPixmapFragments() function. The variables x, y, width and height are used to calculate the target rectangle that is drawn. x and y denotes the center of the target rectangle. The width and height in the target rectangle is scaled by the scaleX and scaleY values. The resulting target rectangle is then rotated rotation degrees around the x, y center point.

根据 Qt5 中的 http://qt.apidoc.info/5.1.1/qtgui/qpainter-pixmapfragment.html,您的代码应如下所示:

void ButtonSelector::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    //painter->drawPixmap(m_backGnd.rect(), m_backGnd);
    QRectF rectSrc = QRectF(m_backGnd.rect());
    QRectF rectTrg = boundingRect();
    QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(rectTrg.center(), rectSrc, rectTrg.width() / rectSrc.width(), rectTrg.height() / rectSrc.height());
    painter->drawPixmapFragments(&fragment,1,m_backGnd, QPainter::OpaqueHint);
    // I've change it to this call:
    // oldqt::drawPixmapFragments(painter, &rectTrg, &rectSrc, 1, m_backGnd, QPainter::OpaqueHint);
    // where oldqt::drawPixmapFragments is function from above

    // ... some other code unrelated to the question
}