如何根据 QGraphicScene 缩放/调整 QGraphicsWidget 的大小?

Posted

技术标签:

【中文标题】如何根据 QGraphicScene 缩放/调整 QGraphicsWidget 的大小?【英文标题】:How do I scale/resize a QGraphicsWidget based on the QGraphicScene? 【发布时间】:2018-08-28 15:39:51 【问题描述】:

我希望我的 QGraphicsWidget 根据场景的大小来缩放它的大小。我目前拥有的 QGraphicsWidget 是一个固定大小,具体取决于 sizeHint 的返回值(QGraphicsWidget 始终为 200 x 200)。下面附上最小的例子:

MainWindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include <QGraphicsScene>
#include <QGraphicsView>

#include "RectangleWidget.h"

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QGraphicsScene * m_scene;
    QGraphicsView * m_view;
    RectangleWidget * m_rectangleWidget;
;

#endif // MAINWINDOW_H

MainWindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)

    ui->setupUi(this);

    m_scene = new QGraphicsScene(this);

    m_view = new QGraphicsView(m_scene, this);
    m_view->setAlignment(Qt::AlignLeft | Qt::AlignTop);

    m_rectangleWidget = new RectangleWidget();

    m_scene->addItem(m_rectangleWidget);

    setCentralWidget(m_view);


MainWindow::~MainWindow()

    delete ui;

矩形小部件.h:

#ifndef RECTANGLEWIDGET_H
#define RECTANGLEWIDGET_H

#include <QGraphicsLinearLayout>
#include <QGraphicsWidget>


class RectangleWidget: public QGraphicsWidget

public:
    RectangleWidget(QGraphicsWidget* parent = nullptr);

    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;

    void setGeometry(const QRectF &geom) override;
    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
;

#endif // RECTANGLEWIDGET_H

矩形小部件.cpp:

#include "rectanglewidget.h"
#include <QPainter>

RectangleWidget::RectangleWidget(QGraphicsWidget* parent)




void RectangleWidget::paint(QPainter *painter,
    const QStyleOptionGraphicsItem *option, QWidget *widget /*= 0*/)

    Q_UNUSED(widget);
    Q_UNUSED(option);

    //Draw border
    painter->drawRoundedRect(boundingRect(), 0.0, 0.0);



QRectF RectangleWidget::boundingRect() const


    return QRectF(QPointF(0,0), geometry().size());


void RectangleWidget::setGeometry(const QRectF &geom)

    prepareGeometryChange();
    QGraphicsLayoutItem::setGeometry(geom);
    setPos(geom.topLeft());


QSizeF RectangleWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const

    switch (which) 
    case Qt::MinimumSize:
        return QSizeF(200, 200);

    default:
        break;
    
    return constraint;

对此的任何帮助将不胜感激。

【问题讨论】:

小部件的大小究竟应该如何取决于场景的大小?他们应该平等吗? 任何比例都可以。让我们继续使用 1/2 的场景大小。 【参考方案1】:

背景

您的 QGraphicsWidget 必须注意两件事:

    添加到场景时

为此,您必须重新实现 QGraphicsWidget::itemChange 并查找 QGraphicsItem::ItemSceneHasChanged 类型的更改。

    当此场景的大小发生变化时

这可以通过将插槽或 lambda 函数连接到 QGraphicsScene::sceneRectChanged 信号来完成。

解决方案

根据给定的解释,我的解决方案如下:

RectangleWidget.hQSizeF sizeHint(Qt::SizeHint which, const QSizeF &amp;constraint = QSizeF()) const override;之后添加:

protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;

private:
    QSize m_rectSize;

RectangleWidget.cpp 中将 return QSizeF(200, 200); 更改为 return m_rectSize; 并在末尾添加:

QVariant RectangleWidget::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)

    if (change == ItemSceneHasChanged) 
        connect(value.value<QGraphicsScene *>(), &QGraphicsScene::sceneRectChanged, [this](const QRectF &rect)
            m_rectSize.setWidth(rect.size().width());
            m_rectSize.setHeight(rect.size().height());
        );
    

    return QGraphicsWidget::itemChange(change, value);

最后,在MainWindow.cppm_scene-&gt;addItem(m_rectangleWidget);之后设置sceneRect如下:

m_scene->setSceneRect(0, 0, 100, 400);

注意:矩形会响应场景的变化,而不是视图。所以如果你调整窗口大小,矩形不会被调整大小。

调整

这将使矩形与场景的大小完全相同。如果你想要不同的比率,说0.5,而不是m_rectSize.setWidth(rect.size().width());,分别写m_rectSize.setWidth(rect.size().width() / 2);m_rectSize.setHeight(rect.size().height() / 2);

【讨论】:

我现在得到了一个 50x200 的固定矩形,现在有你的更改。我们是不是错过了什么。可以发完整的 4 个文件吗? 有没有办法将窗口大小与场景大小联系起来? @MichaelJapzon,有。然而,这已经是另一个问题,需要另一种解决方案。充其量将这个标记为已解决并询问另一个关于 QGraphicsView 的信息。

以上是关于如何根据 QGraphicScene 缩放/调整 QGraphicsWidget 的大小?的主要内容,如果未能解决你的问题,请参考以下文章

在 QGraphicScene 中动态调整视频大小

如何在android中根据谷歌地图不同的缩放级别调整谷歌地图标记的大小

Objective c 如何根据图像大小缩放图像视图大小(高度)

根据缩放 Google 地图 v3 调整标记大小

如何根据缩放、分辨率和窗口大小正确缩放网页?

如何根据 CGSize 更改缩放 CGPoint?