【问题标题】:Painting over QGraphicsItem without scaling在 QGraphicsItem 上绘画而不缩放
【发布时间】:2018-07-25 12:32:43
【问题描述】:

我有一个从 QGraphicsRectItem 派生的自定义类。我只需要在这个项目上画一个框架,然后在右下角画一些块。框架的宽度和块的大小是固定的,但是可以使用 QGraphicsItem::setTransform 函数来缩放项目。问题是当我尝试将项目的边界矩形映射到视图时,我得到一个不准确的输出矩形,并且这个矩形超出了项目的边界。请看下面的代码:

#ifndef TEST_H
#define TEST_H

#include "ui_Test.h"

#include <QGraphicsRectItem>

class MyItem : public QGraphicsRectItem
{
public:
    explicit MyItem(QGraphicsItem *parent = Q_NULLPTR);

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) Q_DECL_OVERRIDE;

private:
    void drawVolumeIndicator(QPainter *painter);
};

class Test : public QMainWindow, private Ui::TestClass
{
    Q_OBJECT

public:
    explicit Test(QWidget *parent = Q_NULLPTR);
};

#endif // TEST_H
#include "Test.h"

#include <QGraphicsScene>
#include <QGraphicsView>

MyItem::MyItem(QGraphicsItem *parent)
    : QGraphicsRectItem(parent)
{}

void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QGraphicsRectItem::paint(painter, option, widget);

    drawVolumeIndicator(painter);
}

void MyItem::drawVolumeIndicator(QPainter *painter)
{
    static const auto blockColor = QColor(QStringLiteral("#0097a7"));
    static const auto frameColor = QColor(QStringLiteral("#660097a7"));

    static Q_CONSTEXPR auto blockSize = QSize(12, 40);
    static Q_CONSTEXPR auto blockMargin = 2;
    static Q_CONSTEXPR auto frameWidth = 4;

    const auto outputRect = painter->transform().mapRect(boundingRect());

    painter->save();
    painter->resetTransform();

    // draw block
    const auto x = outputRect.right() - frameWidth - blockMargin - blockSize.width();
    const auto y = outputRect.bottom() - frameWidth - blockMargin - blockSize.height();
    painter->fillRect(QRect(QPoint(x, y), blockSize), blockColor);

    // draw frame
    painter->setBrush(Qt::transparent);
    painter->setPen(QPen(frameColor, frameWidth, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
    painter->drawRect(outputRect);

    painter->restore();
}

Test::Test(QWidget *parent)
    : QMainWindow(parent)
{
    setupUi(this);

    resize(200, 400);

    auto item = new MyItem;
    item->setBrush(Qt::lightGray);
    item->setPen(QPen(Qt::transparent));
    item->setRect(0, 0, 100, 100);

    // set scale for the item
    QTransform transform;
    transform.scale(1, 3);
    item->setTransform(transform);

    auto scene = new QGraphicsScene;
    scene->addItem(item);

    auto view = new QGraphicsView;
    view->setScene(scene);

    QMainWindow::setCentralWidget(view);
}

以下是未缩放时的外观:

这是缩放后的样子:

【问题讨论】:

  • 您希望块以与矩形相同的方式缩放吗?
  • @eyllanesc,块和框架要画不缩放
  • 如果你意识到块没有被缩放,因为它的大小是独立的,但是框架取决于boundingRect(),并且在你执行缩放时会影响boundingRect()。你为什么不给框架设置一个固定的尺寸,这样你就不会遇到比例问题?
  • @eyllanesc,如果我将缩放应用到框架,那么框架的宽度也会被缩放。我还需要获得准确的映射输出矩形来计算块的位置。如果你放大附加的图像,你会看到在不同的比例下我得到不同的映射输出矩形。
  • 我看到两个块的大小相同,有或没有比例:imgur.com/a/J7qXe

标签: qt5 qgraphicsitem


【解决方案1】:

解决办法是给item设置空笔,同时在画框的时候调整输出rect。所以,最后,我的代码如下所示:

#include "Test.h"

#include <QDebug>
#include <QGraphicsScene>
#include <QGraphicsView>

MyItem::MyItem(QGraphicsItem *parent)
    : QGraphicsRectItem(parent)
{}

void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QGraphicsRectItem::paint(painter, option, widget);

    drawVolumeIndicator(painter);
}

void MyItem::drawVolumeIndicator(QPainter *painter)
{
    static const auto blockColor = QColor(QStringLiteral("#0097a7"));
    static const auto frameColor = QColor(QStringLiteral("#660097a7"));

    static Q_CONSTEXPR auto blockSize = QSize(12, 40);
    static Q_CONSTEXPR auto blockMargin = 2;
    static Q_CONSTEXPR auto frameWidth = 4;
    static Q_CONSTEXPR auto halfFrameWidth = frameWidth / 2;

    const auto outputRect = painter->transform().mapRect(boundingRect());

    painter->save();
    painter->resetTransform();

    // draw block
    const auto x = outputRect.right() - frameWidth - blockMargin - blockSize.width();
    const auto y = outputRect.bottom() - frameWidth - blockMargin - blockSize.height();
    painter->fillRect(QRect(QPoint(x, y), blockSize), blockColor);

    // draw frame
    painter->setBrush(Qt::transparent);
    painter->setPen(QPen(frameColor, frameWidth, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
    painter->drawRect(outputRect.adjusted(halfFrameWidth, halfFrameWidth, -halfFrameWidth, -halfFrameWidth));

    painter->restore();
}

Test::Test(QWidget *parent)
    : QMainWindow(parent)
{
    setupUi(this);

    resize(200, 400);

    auto item = new MyItem;
    item->setBrush(Qt::lightGray);
    item->setPen(Qt::NoPen);
    item->setRect(0, 0, 100, 100);

    // set scale for the item
    QTransform transform;
    transform.scale(1, 3);
    item->setTransform(transform);

    auto scene = new QGraphicsScene;
    scene->addItem(item);

    auto view = new QGraphicsView;
    view->setScene(scene);

    QMainWindow::setCentralWidget(view);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 2020-08-12
    相关资源
    最近更新 更多