目录
一、基本概念
Qt 的图形视图框架(Graphics View Framework)提供了一套用于显示和管理2D图形对象的框架。它提供了一组类,这些类可以组合使用来构建用户界面、处理图形对象、实现缩放、平移、旋转等操作。以下是Qt GraphicsView
框架的主要组件和结构分析:
-
场景(Scene):
QGraphicsScene
是GraphicsView
的核心概念之一。场景充当图形项(Item)的容器,它负责管理图形项的添加、移动、删除以及事件分发。场景可以是一个虚拟的2D绘图区域,你可以在其中添加各种图形项。 -
图形项(Item):图形项是场景中的可视元素,可以是图形、文本、图像等。
QGraphicsItem
是图形项的基类,你可以从它派生自定义的图形项。图形项可以在场景中放置、移动和变换,它们可以响应用户交互和事件。 -
视图(View):
QGraphicsView
是图形场景的可视化表示,它负责将场景中的图形项渲染到屏幕上。视图可以进行缩放、平移、旋转等操作,以便用户查看和交互场景中的图形项。 -
图形引擎(Graphics Engine):Qt的
GraphicsView
框架使用了图形引擎来进行渲染。这允许你在不同平台上以高性能方式呈现图形。通常情况下,Qt使用了底层的OpenGL或者软件渲染引擎,具体取决于平台和配置。 -
视图框架(View Framework):
GraphicsView
提供了视图框架,允许你创建多个视图以查看同一个场景,或者在多个场景之间切换。这对于复杂的图形界面或需要多个视图的应用程序非常有用。 -
事件处理(Event Handling):
GraphicsView
框架允许图形项响应用户事件,例如鼠标点击、拖拽、键盘输入等。你可以重写图形项的事件处理函数以实现自定义的交互逻辑。 -
图形项组合(Item Composition):图形项可以嵌套在组合项中,以形成更复杂的结构。这允许你创建复杂的图形元素,例如符号、图标或者自定义图形。
-
坐标转换(Coordinate Transformations):
GraphicsView
框架提供了用于坐标转换的功能,这允许你将图形项坐标从场景坐标系转换为视图坐标系,以便正确呈现图形。 -
选择和焦点(Selection and Focus):
GraphicsView
框架支持图形项的选择和焦点处理。用户可以选择图形项并将焦点设置到它们上,这对于编辑应用程序非常有用。 -
动画(Animation):你可以使用Qt的动画框架与
GraphicsView
结合,实现动画效果来移动、旋转、缩放图形项。
总之,Qt的GraphicsView
框架提供了一个强大的工具,用于创建自定义的2D图形界面和图形应用程序。它使得开发者能够方便地创建交互式的图形应用程序,支持丰富的图形元素、事件处理和视图操作。
二、场景QGraphicsScene类
QGraphicsScene
是 Qt 中 GraphicsView
框架的一个核心类,用于管理2D图形项(QGraphicsItem
)的容器,充当图形场景的背景。它提供了一种用于创建、排列、渲染和交互图形项的机制。下面是关于 QGraphicsScene
类的一些重要信息:
场景的创建:你可以通过创建一个 QGraphicsScene
的实例来初始化一个场景。通常,你可以在应用程序的主窗口或一个视图中创建场景。
1 |
|
添加和删除图形项:使用场景的 addItem
函数可以将图形项添加到场景中,使用 removeItem
函数可以从场景中删除图形项。
1 2 |
|
场景尺寸:场景可以具有自定义的尺寸,可以使用 setSceneRect
函数设置场景的矩形区域。
1 |
|
场景视图关联:场景通常与一个或多个视图(QGraphicsView
)相关联,视图用于在屏幕上呈现场景中的图形项。你可以在视图中显示同一个场景,也可以创建多个场景和视图的组合。
1 |
|
事件处理:场景可以处理和分发鼠标事件、键盘事件和其他事件给场景中的图形项。你可以重写场景的事件处理函数来处理这些事件。
选择和焦点:场景支持图形项的选择和焦点,用户可以选择图形项并设置焦点。你可以使用 setSelectionArea 和 clearSelection 来控制选择,使用 setFocusItem 来设置焦点图形项。
场景的渲染:场景可以呈现自己的图形项,也可以与视图协同工作来渲染图形。它支持对图形项的渲染和更新。
三、图形项QGraphicsItem类
QGraphicsItem
类是 Qt 中 GraphicsView
框架的核心类之一,用于表示2D图形场景中的图形项。它提供了一个抽象基类,可以通过继承它来创建自定义的图形项,以便在场景中渲染、排列和与用户进行交互。
在它的基础上可以继承出各种图元类,Qt已经预置的包括直线(QGraphicsLineItem)、椭圆(QGraphicsEllipseItem)、文本图元(QGraphicsTextItem)、矩形(QGraphicsRectItem)等。
四、视图QGraphicsView类
QGraphicsView
类是 Qt 中 GraphicsView
框架的一个核心组件,用于将2D图形场景中的图形项渲染到屏幕上,同时提供了视图操作的功能,如缩放、平移、旋转等。
QGraphicsView
类的主要特性和功能:
-
场景显示:
QGraphicsView
用于显示QGraphicsScene
中的图形项,它充当了场景的可视化表示。一个QGraphicsView
可以关联一个或多个场景,允许你在同一个视图中显示多个场景。 -
坐标系:
QGraphicsView
具有自己的视图坐标系,这意味着你可以对视图进行缩放、平移和旋转操作,而不影响场景中的图形项。你可以使用setTransform()
函数来设置视图的变换。 -
视图操作:视图允许用户进行交互操作,例如放大、缩小、平移和旋转图形。用户可以使用鼠标或键盘来执行这些操作。视图的滚动条和工具栏通常用于提供这些操作。
-
背景和边框:视图可以有自定义的背景和边框,你可以设置视图的背景颜色、图片或渐变,以及边框样式和颜色。
-
绘制优化:
QGraphicsView
通过使用视图坐标系和场景坐标系之间的坐标转换来实现部分绘制和绘制优化。这有助于提高性能,只有可见部分的图形项会被绘制。 -
事件处理:
QGraphicsView
可以处理鼠标事件、键盘事件和其他事件,允许用户与图形进行交互。你可以重写视图的事件处理函数以自定义交互行为。 -
多视图:你可以创建多个
QGraphicsView
实例并显示相同的或不同的场景。这对于创建多个视图查。
五、项目中的使用
在停车管控项目中,对于抓拍的过车图片有时候需要进行放大查看局部细节(如车牌号、驾驶人员等),对于此种场景可以使用图形视图框架加载过车图片,从而很方便的进行图片的拖拽和缩放,便于查看细节。
5.1 自定义图片缩放组件类定义
#pragma once
#include <QWidget>
#include<QGraphicsScene>
#include<QGraphicsView>
#include<QGraphicsPixmapItem>
#include<QMouseEvent>
#include<QPoint>
class QPixmapScalableView : public QGraphicsView
{
Q_OBJECT
public:
QPixmapScalableView(QWidget *parent = Q_NULLPTR);
~QPixmapScalableView();
void setPixMapPath(const QString&imgPath);
protected:
void wheelEvent(QWheelEvent *event) override;
void QPixmapScalableView::mousePressEvent(QMouseEvent *event) override;
void QPixmapScalableView::mouseMoveEvent(QMouseEvent *event) override;
void QPixmapScalableView::mouseReleaseEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
void initUI();
void scaleImage(bool bZoomIn);
QGraphicsScene*m_pScene = nullptr;
QGraphicsPixmapItem *m_pixmapItem = nullptr;
QString m_imgPath;
bool m_bDragging = false;
QPoint m_dragStartPosition;//拖动起始位置
};
5.2 自定义图片缩放组件实现
#include "QGraphicsViewWidget.h"
#include <QVBoxLayout>
#include <QtWidgets/QApplication>
#define MIN_SCALE_FACTOR 0.1
#define MAX_SCALE_FACTOR 10.0
QPixmapScalableView::QPixmapScalableView(QWidget *parent)
: QGraphicsView(parent)
{
//ui.setupUi(this);
initUI();
}
void QPixmapScalableView::setPixMapPath(const QString&imgPath)
{
if (!imgPath.isEmpty())
{
m_imgPath = imgPath;
// 加载图片并添加到场景中
m_pixmapItem = m_pScene->addPixmap(QPixmap(m_imgPath));
m_pixmapItem->setFlags(QGraphicsItem::ItemIsMovable);
}
}
void QPixmapScalableView::initUI()
{
// 创建图形场景
m_pScene = new QGraphicsScene(this);
this->setScene(m_pScene);//设置场景
this->setRenderHint(QPainter::Antialiasing);//反走样
this->setDragMode(QGraphicsView::ScrollHandDrag);
this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);//水平Bar
this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);//储值Bar
// 布局
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(this);
//setLayout(layout);
this->setMouseTracking(true);
this->setFocus();
this->show();
}
void QPixmapScalableView::scaleImage(bool bZoomIn)
{
qreal currentScaleX = this->transform().m11();
qreal currentScaleY = this->transform().m22();
// 计算新的缩放因子
qreal factor = bZoomIn ? 1.05 : 0.95;
qreal newScaleX = currentScaleX * factor;
qreal newScaleY = currentScaleY * factor;
qreal imgSacleX = qBound(MIN_SCALE_FACTOR, newScaleX, MAX_SCALE_FACTOR);
qreal imgSacleY = qBound(MIN_SCALE_FACTOR, newScaleY, MAX_SCALE_FACTOR);
//QTransform::fromScale(dx,dy)创建一个缩放变换。
//dx,dy为x和y方向缩放因子;返回在x和y方向上缩放变换QTransform对象。
//QTransform::fromTranslate(dx,dy) 穿件平移变换对象
this->setTransform(QTransform::fromScale(imgSacleX, imgSacleY));
}
void QPixmapScalableView::mousePressEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton) {
m_dragStartPosition = event->pos();
setCursor(Qt::ClosedHandCursor);
}
}
void QPixmapScalableView::mouseMoveEvent(QMouseEvent *event) {
if (event->buttons() & Qt::LeftButton) {
QPoint delta = event->pos() - m_dragStartPosition;
//图形项拖动距离大于最小的拖动距离
if (delta.manhattanLength() > qApp->startDragDistance()) {
setCursor(Qt::ClosedHandCursor);
m_bDragging = true;
}
}
else {
setCursor(Qt::OpenHandCursor);
}
}
void QPixmapScalableView::mouseReleaseEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton && m_bDragging) {
m_bDragging = false;
//setCursor(Qt::OpenHandCursor);
}
}
void QPixmapScalableView::keyPressEvent(QKeyEvent *event){
// 处理键盘事件以进行缩放
if (event->key() == Qt::Key_Up) {
scaleImage(true);
}
else if (event->key() == Qt::Key_Down) {
scaleImage(false); // 缩小
}
}
void QPixmapScalableView::wheelEvent(QWheelEvent *event){
if (m_bDragging) return;
bool bZoomIn = event->angleDelta().y() > 0;
scaleImage(bZoomIn);
}
QPixmapScalableView::~QPixmapScalableView()
{
}
5.3 自定义图片缩放组件使用
{
//...
p_Image = new QPixmapScalableView(ui.widget);
p_Image->setPixMapPath(":/Images/images/20231012132755_贵A****.png");
// 布局
QVBoxLayout *layout = new QVBoxLayout(ui.widget);
layout->addWidget(p_Image);
setLayout(layout);
}