https://blog.csdn.net/qq769651718/article/details/79357936
使用QPushButton、QLabel、QCheckBox等構成GUI的控件或自定義圖形時,開發應用程序會變得很簡單。
但是如果想在GUI中使用數十個或者數百個圖形對象,向用戶完美展示控制場景,則會受到很多的限制。
圖形視圖框架用來管理2D圖形項,支持繪制、縮放、事件響應等等。
1、快速提供並管理大量對象
2、將事件傳遞到每一個對象
3、管理焦點處理或對象選擇等狀態
圖形視圖框架是按照MVC設計模式繪圖, MVC設計模式包括三個元素:數據的模型(Model),用戶界面的視圖(View) ,用戶再界面上的操作控制Controller。
QGraphicsView
QGraphicsView 是為了在場景上顯示圖元而提供的類。QGraphicsView包括可視控件區域和用於顯示大場景滾動區域,可以接受用戶輸入事件。QGraphicsView間接繼承至QWidget。
QGraphicsScene
QGraphicsScene類可以保存圖元,也可以處理用戶輸入事件。是圖形對象QGraphicsItem的容器,為管理大量的items提供一個快速的接口。QGraphicsScene只繼承自QObject,所以本身是不可見的,必須通過與之相連的視圖類QGraphicsView來顯示.
QGraphicsItem
QGraphicsItem是為了在圖形視圖上實現圖形對象而提供的類。支持鼠標、鍵盤、焦點事件,支持拖放,在它的基礎上可以繼承出各種圖元類。支持碰撞檢測collision detection.
1 QGraphicsScene的常用函數
常用添加圖元函數
QGraphicsScene::setBackgroundBrush //填充背景色
QGraphicsScene::setForegroundBrush //填充前景色
QGraphicsScene::addSimpleText //添加簡單文本
QGraphicsScene::addLine //添加直線
QGraphicsScene::addRect //添加矩形
QGraphicsScene::addEllipse //添加橢圓
QGraphicsScene::addWidget //添加窗口
QGraphicsScene::addPixmap //添加圖片
例如:
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QLabel>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
/*設置場景的背景色前景色*/
scene.setBackgroundBrush(QBrush(Qt::red));
scene.setForegroundBrush(QBrush(QColor(0, 255, 0, 50)));
/*添加線*/
scene.addLine(0, 0, 100, 100, QPen(Qt::black));
/*添加矩形*/
scene.addRect(0, 100, 100, 100, QPen(Qt::yellow), QBrush(Qt::blue));
/*添加橢圓*/
scene.addEllipse(100, 0, 100, 100, QPen(Qt::red), QBrush(Qt::green));
/*添加簡單文本,並且設置文本字體,並且描邊*/
scene.addSimpleText("hello", QFont("system", 40))
->setPen(QPen(QBrush(Qt::yellow), 3));
/*添加圖片,並且移動位置*/
scene.addPixmap(QPixmap("E:\\qt_workspace\\pic\\wallet.png"))
->setPos(200, 200);
/*添加一個窗口*/
QLabel label("widget");
scene.addWidget(&label);
return app.exec();
}
操作圖元函數
QGraphicsScene::itemAt //查找場景某個中最表層的item
QGraphicsScene::setSelectionArea //設置選定區域
QGraphicsScene::setSceneRect //設置場景的區域大小
QGraphicsScene::itemsBoundingRect //根據所有的item計算區域大小
QGraphicsScene:: selectedItems //獲取被選中的item,item必須為可選QGraphicsItem::ItemIsSelectable
2 QGraphicsItem的常用函數
QGraphicsItem::rect //不帶邊框的圖形區域
QGraphicsItem::boundingRect //帶邊框的圖形區域
QGraphicsItem::collidesWithItem //碰撞檢測
QGraphicsItem::setScale //縮放
QGraphicsItem::setRotation //旋轉
QGraphicsItem::setZValue //設置z坐標,圖元的疊加先后順序可以用它來設置
QGraphicsItem::setPos //設置位置坐標
設置item的屬性
void QGraphicsItem::setFlags(GraphicsItemFlags flags);
/*
*參數GraphicsItemFlags flags 為枚舉類型,可以以下值
* QGraphicsItem::ItemIsMovable 是否可以移動
* QGraphicsItem::ItemIsSelectable 是否可以被選中
* QGraphicsItem::ItemIsFocusable 是否可以設置為焦點item
*/
3 圖形視圖的坐標系
3.1 QGraphscItem圖元坐標系
圖元對象都有自身的坐標系,坐標系以(0,0)為坐標原點,自左向右遞增是x軸,自上而下遞增是y軸,而且所有圖元對象的移動轉換作用點都是(0, 0),坐標值可以是浮點型數值。
3.2 QGraphicsScene場景坐標系
場景坐標系是所有圖元對象的絕對坐標. 有四個象限。坐標系以(0,0)為坐標原點,自左向右遞增是x軸,自上而下遞增是y軸,坐標值可以是浮點型數值。
3.3 QGraphicsView視圖坐標系
視圖坐標是窗口坐標。視圖中的坐標單位1個像素。
3.4 坐標映射
父子圖元坐標映射
QGraphicsItem::mapToParent //子圖元坐標映射到父圖元
QGraphicsItem::mapFromParent //父圖元坐標映射到子圖元
圖元與場景坐標映射
QGraphicsItem::mapToScene //圖元到場景
QGraphicsItem::mapFromScene //場景到圖元
場景與視圖坐標映射
QGraphicsView::mapFromScene //場景到視圖
QGraphicsView::mapToScene //視圖到場景
3.5 調整坐標系
調整坐標系的的類是QTransform、QMatrix,這兩個類都提供了縮放、旋轉、變形坐標系的方法。
3.5.1 調整QGraphicsVeiw坐標系
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QLabel>
#include <QTransform>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
QTransform transform;
//transform.translate(100, 0); //移動坐標原點
transform.scale(1.5, 1); //縮放
//transform.rotate(10); //旋轉
// transform.shear(0.1, 0.1); //變形
view.setTransform(transform);
/*添加矩形*/
scene.addRect(0, 100, 100, 100, QPen(Qt::yellow), QBrush(Qt::blue));
return app.exec();
}
3.5.2 調整QGraphicsItem坐標系
#include <QApplication>
#include <QGraphicsView>
#include <QTransform>
#include <QGraphicsRectItem>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
QTransform transform;
//transform.translate(100, 0); //移動坐標原點
transform.scale(1.5, 1); //縮放
//transform.rotate(10); //旋轉
// transform.shear(0.1, 0.1); //變形
/*添加矩形*/
QGraphicsRectItem *rect = scene.addRect(0, 100, 100, 100
, QPen(Qt::yellow), QBrush(Qt::blue));
rect->setTransform(transform);
return app.exec();
}
4 圖形視圖的事件處理
QGraphicsView是窗口類,那么它當然可以處理鼠標、鍵盤等事件。QGraphicsScene
不是窗口類,但是它也能處理鼠標、鍵盤等窗口類的事件。
QGraphicsView收到event,就會轉換成QGraphicsScene的事件,QGraphicsScene對象再傳遞給對應的QGraphicsItem。
4.1 QGraphicsView的事件處理
QGraphicsView的事件處理機制與普通的QWidget相同。
#include "widget.h"
#include <QDebug>
GraphicsView::GraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
}
void GraphicsView::mousePressEvent(QMouseEvent* ev)
{
qDebug() << "GraphicsView" << __FUNCTION__ << endl;
/*必須傳遞到基類的mousePressEvent,否則QGraphicsScene無法收到消息*/
QGraphicsView::mousePressEvent(ev);
}
GraphicsView::~GraphicsView()
{
}
4.2 QGraphicsScene的事件處理
QGraphicsScene的事件處理機制與QWidget不同, 使用QGraphicsSceneEvent來傳遞事件。
例如,鼠標點擊事件的虛函數為:
[virtual protected] void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
scene.cpp
#include "scene.h"
#include <QDebug>
MyScene::MyScene(QObject * parent) : QGraphicsScene(parent)
{
}
void MyScene::mousePressEvent(QGraphicsSceneMouseEvent* ev)
{
qDebug() << "GraphicsScene" << __FUNCTION__ << endl;
/*必須傳遞到基類的mousePressEvent中,否則QGraphicsItem無法收到消息*/
QGraphicsScene::mousePressEvent(ev);
}
4.3 QGraphicsItem的事件處理
QGraphicsItem的事件處理函數傳遞事件也是使用的QGraphicsSceneEvent。
常用的事件處理函數有:
//鼠標按下事件,場景上面的鼠標事件的觸發位置坐標需要使用mouseEvent->scenePos()來獲取
[virtual protected] void QGraphicsScene::mousePressEvent(
QGraphicsSceneMouseEvent *mouseEvent)
//鼠標釋放事件
[virtual protected] void QGraphicsScene::mouseReleaseEvent(
QGraphicsSceneMouseEvent *mouseEvent)
//鼠標移動事件
[virtual protected] void QGraphicsScene::mouseMoveEvent(
QGraphicsSceneMouseEvent *mouseEvent)
//鼠標滾輪事件
[virtual protected] void QGraphicsScene::wheelEvent(
QGraphicsSceneWheelEvent *wheelEvent)
/*注意:先使用void QGraphicsItem::setAcceptHoverEvents(bool enabled),才能接收到hoverevent*/
//鼠標進入事件
[virtual protected] void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
//鼠標離開事件
[virtual protected] void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
//鼠標不點擊移動事件
[virtual protected] void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
/*鍵盤按下事件 setFlags(QGraphicsItem::ItemIsFocusable); 再調用setFocus才能接受鍵盤事件*/
[virtual protected] void QGraphicsItem::keyPressEvent(QKeyEvent *event)
//鍵盤釋放事件
[virtual protected] void QGraphicsItem::keyReleaseEvent(QKeyEvent *event)
//繪畫事件
[pure virtual] void QGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR)
5 圖形視圖的內存管理
QGraphicsView通過指定父窗口托管內存, QGraphicsScene通過指定父QObject對象托管內存。QGraphicsItem 通過指定父QGraphicsItem對象托管內存, 頂級QGraphicsItem對象通過QGraphicsScene對象托管。
6 圖形視圖碰撞檢測
所謂的碰撞檢測,就是判斷某個點是否在圖元對象中,或者兩個圖元是否有接觸。
//判斷QGraphicsItem坐標系中某點, 是否包含在QGraphicsItem中,需要將點轉換成QGraphicsItem坐標
QGraphicsItem::contains()
//item的矩形邊框
QGraphicsItem::boundingRect()
//返回item的形狀path,可以是任何形狀。
QGraphicsItem::shape()
//判斷是否與某個item碰撞
QGraphicsItem::collidesWithItem
QGraphicsScene認為所有圖元的boundingRect函數與shape函數都是不發生改變的,除非用戶進行通知。
如果你想改變一個圖元的范圍,必需先調用prepareGeometryChange以允許QGraphicsScene進行更新。
7 背景緩沖
如果場景的背景需要大量耗時的渲染,可以利用背景緩存,當下次需要渲染背景時,可以快速進行渲染。它的原理就是,把整個視口先繪制到一個QPixmap上。
但是這個只適合較小的視口,也就是說,如果視圖窗口很大,而且有滾動條,那么就不再適合緩存背景。
我們可以使用setCacheMode(QGraphicsView::CacheBackground)來設置背景緩存,默認設置是沒有緩存QGraphicsView::CacheNone。
void QGraphicsView::setCacheMode(CacheMode mode);
8 打印QGraphicsScene
將整個場景打印到一個QPainterDevice的派生類對象中,例如QPixmap。
main.cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
scene.addRect(0, 0, 100, 100, QPen(Qt::red), QBrush(Qt::yellow));
QPixmap pixmap(scene.sceneRect().width(), scene.sceneRect().height());
pixmap.fill(QColor(0, 0, 0, 0));
QPainter painter;
painter.begin(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
scene.render(&painter);
painter.end();
pixmap.save("d:\\123.png");
return app.exec();
}
9 圖形效果疊加
Qt中可以給圖元添加特效,QGraphicsEffect為特效基本類。
有以下具體特效
QGraphicsBlurEffect //模糊效果
QGraphicsDropShadowEffect //陰影效果
QGraphicsColorizeEffect //使用色調的着色效果
QGraphicsOpacityEffect //透明效果
例如:main.cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QGraphicsBlurEffect>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
view.show();
view.resize(400, 400);
QGraphicsBlurEffect effect;
effect.setBlurRadius(10);
QGraphicsRectItem* rect = scene.addRect(0, 0, 100, 100, QPen(Qt::red), QBrush(Qt::yellow));
rect->setGraphicsEffect(&effect);
return app.exec();
}
---------------------
作者:嚇人的猿
來源:CSDN
原文:https://blog.csdn.net/qq769651718/article/details/79357936
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!