QT 圖形視圖框架


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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM