我如何 scale/resize 基于 QGraphicSscene 的 QGraphicsWidget?
How do I scale/resize a QGraphicsWidget based on the QGraphicScene?
我希望我的 QGraphicsWidget 根据场景的大小来缩放它的大小。我目前拥有的 QGraphicsWidget 是固定大小,具体取决于 sizeHint 的 return 值(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;
}
RectangleWidget.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
RectangleWidget.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;
}
如有任何帮助,我们将不胜感激。
背景
您的 QGraphicsWidget 必须注意两件事:
- 添加到场景时
为此,您必须重新实现 QGraphicsWidget::itemChange
并寻找类型更改 QGraphicsItem::ItemSceneHasChanged
.
- 当这个场景的大小改变时
这可以通过将插槽或 lambda 函数连接到 QGraphicsScene::sceneRectChanged
信号来完成。
解决方案
根据给定的解释,我的解决方案如下:
在RectangleWidget.h中QSizeF sizeHint(Qt::SizeHint which, const QSizeF &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.cpp后m_scene->addItem(m_rectangleWidget);
设置sceneRect
如下:
m_scene->setSceneRect(0, 0, 100, 400);
注意:矩形会响应场景的变化,而不是视图的变化。因此,如果您调整 window 的大小,矩形将不会调整大小。
调整
这将使矩形与场景的大小完全相同。如果你想要一个不同的比率,说 0.5
,而不是 m_rectSize.setWidth(rect.size().width());
写 m_rectSize.setWidth(rect.size().width() / 2);
,分别 m_rectSize.setHeight(rect.size().height() / 2);
.
我希望我的 QGraphicsWidget 根据场景的大小来缩放它的大小。我目前拥有的 QGraphicsWidget 是固定大小,具体取决于 sizeHint 的 return 值(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;
}
RectangleWidget.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
RectangleWidget.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;
}
如有任何帮助,我们将不胜感激。
背景
您的 QGraphicsWidget 必须注意两件事:
- 添加到场景时
为此,您必须重新实现 QGraphicsWidget::itemChange
并寻找类型更改 QGraphicsItem::ItemSceneHasChanged
.
- 当这个场景的大小改变时
这可以通过将插槽或 lambda 函数连接到 QGraphicsScene::sceneRectChanged
信号来完成。
解决方案
根据给定的解释,我的解决方案如下:
在RectangleWidget.h中QSizeF sizeHint(Qt::SizeHint which, const QSizeF &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.cpp后m_scene->addItem(m_rectangleWidget);
设置sceneRect
如下:
m_scene->setSceneRect(0, 0, 100, 400);
注意:矩形会响应场景的变化,而不是视图的变化。因此,如果您调整 window 的大小,矩形将不会调整大小。
调整
这将使矩形与场景的大小完全相同。如果你想要一个不同的比率,说 0.5
,而不是 m_rectSize.setWidth(rect.size().width());
写 m_rectSize.setWidth(rect.size().width() / 2);
,分别 m_rectSize.setHeight(rect.size().height() / 2);
.