QGraphicsView 实例2基本结构和功能实现

Graphics View框架结构”三元素“:场景类(QGraphicsScene)、视图类(QGraphicsView)和图元类(QGraphicsItem)。场景类提供管理位于其中的图元容器,视图类显示场景中的图元,场景可以通过多个视图表现。

QGraphicsScene——场景

主要工作:

1.提供管理大量图形项的快速接口

2.将事件传播给每个图形项

3.管理每个图形项的状态,如:选择状态,焦点状态等

4.管理未经变换的渲染功能,主要用于打印
放置图元的容器,本身不可见,通过关联视图类显示和操作。
QGraphicsScene::addItem()添加图元。
QGraphicsScene::items()返回与点、矩形、多边形或向量路径相交的所有图元。
QGraphicsScene::itemAt()返回指定点的顶层图元。

场景事件发送给图元,同时管理图元间事件传播。场景收到某一点鼠标单击事件,场景会将事件传给这一点的图元。

管理图元事件。
QGraphicsScene::setSelectionArea()  选择图元,选择区域任意形状,QPainterPath表示。
QGraphicsScene::selectedItems()   获得当前选择图元列表。
QGraphicsScene::setFocusItem()或QGraphicsScene::setFocus()设置图元焦点。
QGraphicsScene::focusItem()   获得当前焦点图元。
QGraphicsScene::render()  在绘图设备上绘制场景。

场景坐标:
中心为原点,每个图元都有场景坐标和相应的包容框,等价于QPainter的逻辑坐标,一般以场景中心为原点。

场景还有背景层和前景层,QBrush指定,也可通过drawBackground()和drawForeground()自定义。

场景变化时发射QGraphicsScene::changed()信号,参数说场景的矩形列表,表示发生变化的矩形区。

QGraphicsView——视图

可视窗口,显示场景中图元。同一场景可以多个视图,相同数据集可以不同视图。
视图大于场景时,默认场景在视图的中间显示,也可通过视图的Alignment属性设置场景在视图中的显示位置;视图小于场景时,提供卷滚条显示。
可滚动窗口部件,QGraphicsView::setViewport()将视图设置为QGLWidget。
接收鼠标键盘输入,并翻译为场景事件(转换为场景坐标),然后传送给场景。
QGraphicsView::matrix()变换场景坐标,实现场景缩放和选择。
QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()与场景坐标转换。

视图坐标:
窗口部件的坐标(设备坐标,物理坐标),单位是像素,左上角是(0,0)。
所有鼠标事件最开始都是使用视图坐标。

QGraphicsItem——图形项

直线(QGraphicsLineItem)、椭圆(QGraphicsEllipseItem)、文本图元(QGraphicsTextItem)、矩形(QGraphicsRectItem)等。
主要功能:
鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件    键盘输入事件     拖曳事件
分组(组合),可以是父子项关系组合,可以通过QGraphicsItemGroup类组合 碰撞检测

QGraphicsItem::matrix()函数进行自身的交换,可以包含子图元。

图元坐标:
图元中心为原点(局部逻辑坐标),QGraphicsItem::paint()绘图基准。
QGraphicsItem::boundingRect()局部坐标。
QGraphicsItem:pos()返回图元在父坐标系中的坐标。
QGraphicsItem::scenePos()返回图元在场景中的坐标。
QGraphicsItem::sceneBoundingRect()返回图元在场景中的边界矩形。

基本结构和功能实现

功能实现:

1.工作区时一个从QGraphicsView继承的自定义类QWGraphicsView,作为绘图的视图组件。工作区是一个QGraphicsScene场景,场景大小就是图中实线矩形框的大小。改变窗口大小,当视图大于场景时,矩形框总是在图形视图的中央;当视图小于场景时,在视图窗口自动出现卷滚条

2.蓝色椭圆位于场景的中间,红色的圆位于场景的右下角。当图形项位置不在场景的矩形框中,图形项可以显示。

3.当鼠标在窗口上移动时,会在状态栏显示当前光标位置的视图坐标和场景坐标,在某个图形项上单击鼠标时,还会显示图形项中的局部坐标。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include 
#include 
#include "qmgraphicsview.h"

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    void iniGraphicsSystem(); //创建Graphics View的各项
protected:
    void resizeEvent(QResizeEvent *event);
private slots:
    void on_mouseMovePoint(QPoint point);
    void on_mouseClicked(QPoint point);
private:
    QGraphicsScene  *scene;

    QLabel  *labViewCord;
    QLabel  *labSceneCord;
    QLabel  *labItemCord;

    QWGraphicsView *View;
    QLabel *LabSceneRect;
    QLabel *labViewSize;
    QGroupBox *groupBox;
    QVBoxLayout *groupBoxLayout;
    QWidget *widget;
    QVBoxLayout *mainLayout;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include 
#include 
#pragma execution_character_set("utf-8") //Qt中文乱码、编译报错的解决方案

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    LabSceneRect = new QLabel;
    labViewSize = new QLabel;
    groupBox = new QGroupBox;
    groupBoxLayout = new QVBoxLayout(groupBox);
    groupBoxLayout->addWidget(LabSceneRect);
    groupBoxLayout->addWidget(labViewSize);
    View = new QWGraphicsView;
    widget = new QWidget;
    mainLayout = new QVBoxLayout(widget);
    mainLayout->addWidget(groupBox);
    mainLayout->addWidget(View);
    setCentralWidget(widget);

    labViewCord = new QLabel("View 坐标:");
    labViewCord->setMinimumWidth(150);
    statusBar()->addWidget(labViewCord);

    labSceneCord = new QLabel("Scene 坐标:");
    labSceneCord->setMinimumWidth(150);
    statusBar()->addWidget(labSceneCord);

    labItemCord = new QLabel("Item 坐标:");
    labItemCord->setMinimumWidth(150);
    statusBar()->addWidget(labItemCord);

    View->setCursor(Qt::CrossCursor);
    View->setMouseTracking(true);
    View->setDragMode(QGraphicsView::RubberBandDrag);

    connect(View, SIGNAL(mouseMovePoint(QPoint)), this, SLOT(on_mouseMovePoint(QPoint)));
    connect(View, SIGNAL(mouseClicked(QPoint)), this, SLOT(on_mouseClicked(QPoint)));

    iniGraphicsSystem();
}

void MainWindow::iniGraphicsSystem() { //构造Graphics View的各项
    QRectF rect(-200, -100, 400, 200);
    scene = new QGraphicsScene(rect); //scene逻辑坐标系定义
    View->setScene(scene);
    View->setDragMode(QGraphicsView::RubberBandDrag);

    //画一个矩形框,大小等于scene
    QGraphicsRectItem *item = new QGraphicsRectItem(rect); //矩形框正好等于scene的大小
    item->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsFocusable);  //可选,可以有焦点,但是不能移动
    QPen pen;
    pen.setWidth(2);
    item->setPen(pen);
    scene->addItem(item);

    //一个位于scene中心的椭圆,测试局部坐标
    QGraphicsEllipseItem *item2 = new QGraphicsEllipseItem(-100,-50,200,100); //矩形框内创建椭圆,绘图项的局部坐标,左上角(-100,-50),宽200,高100
    //item2->setPos(0, 0);//缺省位置在scene的(0,0)
    item2->setBrush(QBrush(Qt::blue));
    item2->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsFocusable);
    item2->setSelected(true);
    scene->addItem(item2);

    //一个圆,中心位于scene的边缘
    QGraphicsEllipseItem *item3 = new QGraphicsEllipseItem(-50,-50,100,100); //矩形框内创建椭圆,绘图项的局部坐标,左上角(-100,-50),宽200,高100
    item3->setPos(rect.right(), rect.bottom());
    item3->setBrush(QBrush(Qt::red));
    item3->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsFocusable);
    scene->addItem(item3);

    scene->clearSelection();
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    //窗口变化大小时的事件
    Q_UNUSED(event);
    //Graphics View坐标,左上角总是(0,0),宽度=,长度=
    labViewSize->setText(QString::asprintf(("Graphics View坐标,左上角总是(0,0),宽度=%d,高度=%d"), View->width(),View->height()));

    QRectF rectF = View->sceneRect(); //Scene的矩形区
    LabSceneRect->setText(QString::asprintf("QGraphicsView::sceneRect=(Left, Top, Width, Height) = %.0f, %.0f, %.0f, %.0f",
                                            rectF.left(), rectF.top(), rectF.width(), rectF.height()));
}

void MainWindow::on_mouseMovePoint(QPoint point)
{
    //鼠标移动事件,point是GraphicsView的坐标,物理坐标
    labViewCord->setText(QString::asprintf("View 坐标:%d, %d", point.x(), point.y()));
    QPointF pointScene = View->mapToScene(point); //转换到Scene坐标
    labSceneCord->setText(QString::asprintf("Scene 坐标:%.0f, %.0f", pointScene.x(), pointScene.y()));
}

void MainWindow::on_mouseClicked(QPoint point)
{
    //鼠标单击事件
    QPointF pointScene = View->mapToScene(point); //转换到Scene坐标
    QGraphicsItem  *item = scene->itemAt(pointScene,View->transform()); //获取光标下的绘图项
    if(item != NULL) {//有绘图项
        QPointF pointItem = item->mapFromScene(pointScene); //转换为绘图项的局部坐标
        labItemCord->setText(QString::asprintf("Item 坐标:%.0f, %.0f", pointItem.x(), pointItem.y()));
    }
}

 qmgraphicsview.h

#ifndef QWGRAPHICSVIEW_H
#define QWGRAPHICSVIEW_H

#include 
#include 

class QWGraphicsView : public QGraphicsView {
    Q_OBJECT
public:
    explicit QWGraphicsView(QWidget *parent = 0);
protected:
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
signals:
    void mouseMovePoint(QPoint point);
    void mouseClicked(QPoint point);
};

#endif // QWGRAPHICSVIEW_H
qmgraphicsview.cpp

#include "qmgraphicsview.h"
#include 
#include 

QWGraphicsView::QWGraphicsView(QWidget *parent):QGraphicsView(parent)
{

}

void QWGraphicsView::mouseMoveEvent(QMouseEvent *event) {//鼠标移动事件
    QPoint point = event->pos(); //QGraphicsView的坐标
    emit mouseMovePoint(point); //释放信号
    QGraphicsView::mouseMoveEvent(event);
}

void QWGraphicsView::mousePressEvent(QMouseEvent *event) { //鼠标左键按下事件
    if(event->button()==Qt::LeftButton) {
        QPoint point = event->pos(); //QGraphicsView的坐标
        emit mouseClicked(point);//释放信号
    }
    QGraphicsView::mousePressEvent(event);
}

结果有乱码现象:

QGraphicsView 实例2基本结构和功能实现_第1张图片

 添加:

#pragma execution_character_set("utf-8")

就能解决中文乱码的问题

结果为:

QGraphicsView 实例2基本结构和功能实现_第2张图片

你可能感兴趣的:(qt)