Qt Graphics View 绘图架构
"QWGraphicsView.h" 头文件代码如下:
#pragma once
#include <QGraphicsView>
class QWGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
QWGraphicsView(QWidget *parent);
~QWGraphicsView();
protected:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
signals:
void mouseMovePoint(QPoint point);
void mouseClicked(QPoint point);
};
mouseMoveEvent()是鼠标移动事件,代码如下:
//鼠标移动事件
void QWGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
QPoint point = event->pos();//QGraphicsView的坐标
emit mouseMovePoint(point); //释放信号
QGraphicsView::mouseMoveEvent(event);
}
在此事件响应代码里,通过事件的pos()函数获取鼠标光标在视图中的坐标point,然后作为参数发射 mouseMovePoint(point)信号。这样,若在其他地方编写槽函数与此信号关联,就可以对鼠标移动事件作出响应。
mousePressEvent()是鼠标按键按下事件,代码如下:
//鼠标左键按下事件
void QWGraphicsView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
QPoint point = event->pos();//QGraphicsView的坐标
emit mouseClicked(point);//释放信号
}
QGraphicsView::mousePressEvent(event);
}
在此事件响应代码里,首先判断是否是鼠标左键按下,然后通过事件的pos()函数获取鼠标光标在视图中的坐标point,然后作为参数发射mouseClicked(point)信号。
"sample8_4QGraphicsView.h" 头文件代码如下:
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_sample8_4QGraphicsView.h"
#include <QGraphicsScene>
#include <QLabel>
class sample8_4QGraphicsView : public QMainWindow
{
Q_OBJECT
public:
sample8_4QGraphicsView(QWidget *parent = Q_NULLPTR);
private:
Ui::sample8_4QGraphicsViewClass ui;
protected:
void resizeEvent(QResizeEvent *event);
private:
QGraphicsScene *scene;
QLabel *labViewCord;
QLabel *labSceneCord;
QLabel *labItemCord;
void iniGraphicsSystem(); //创建Graphics View的各项
private slots:
void on_mouseMovePoint(QPoint point);
void on_mouseClicked(QPoint point);
};
#include "sample8_4QGraphicsView.h"
#include "ui_sample8_4QGraphicsView.h"
#include <QGraphicsEllipseItem>
//解决QT中中文显示乱码问题
#pragma execution_character_set("utf-8")
sample8_4QGraphicsView::sample8_4QGraphicsView(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
labViewCord = new QLabel("View 坐标:");
labViewCord->setMinimumWidth(150);
ui.statusBar->addWidget(labViewCord);
labSceneCord = new QLabel("Scene 坐标:");
labSceneCord->setMinimumWidth(150);
ui.statusBar->addWidget(labSceneCord);
labItemCord = new QLabel("Item 坐标:");
labItemCord->setMinimumWidth(150);
ui.statusBar->addWidget(labItemCord);
ui.View->setCursor(Qt::CrossCursor);
ui.View->setMouseTracking(true);
ui.View->setDragMode(QGraphicsView::RubberBandDrag);
QObject::connect(ui.View, SIGNAL(mouseMovePoint(QPoint)),
this, SLOT(on_mouseMovePoint(QPoint)));
QObject::connect(ui.View, SIGNAL(mouseClicked(QPoint)),
this, SLOT(on_mouseClicked(QPoint)));
iniGraphicsSystem();
}
鼠标移动事件响应:
//鼠标移动事件,point是 GraphicsView的坐标,物理坐标
void sample8_4QGraphicsView::on_mouseMovePoint(QPoint point)
{
labViewCord->setText(QString::asprintf("View 坐标:%d,%d", point.x(), point.y()));
QPointF pointScene = ui.View->mapToScene(point); //转换到Scene坐标
labSceneCord->setText(QString::asprintf("Scene 坐标:%.0f,%.0f", pointScene.x(), pointScene.y()));
}
鼠标单击事件响应:
//鼠标单击事件
void sample8_4QGraphicsView::on_mouseClicked(QPoint point)
{
QPointF pointScene = ui.View->mapToScene(point); //转换到Scene坐标
QGraphicsItem *item = NULL;
item = scene->itemAt(pointScene, ui.View->transform()); //获取光标下的绘图项
if (item != NULL) //有绘图项
{
QPointF pointItem = item->mapFromScene(pointScene); //转换为绘图项的局部坐标
labItemCord->setText(QString::asprintf("Item 坐标:%.0f,%.0f", pointItem.x(), pointItem.y()));
}
}
窗口变化大小时的事件:
//窗口变化大小时的事件
void sample8_4QGraphicsView::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
//Graphics View坐标,左上角总是(0,0),宽度=,长度=
ui.labViewSize->setText(QString::asprintf("Graphics View坐标,左上角总是(0,0),宽度=%d,高度=%d",
ui.View->width(), ui.View->height()));
QRectF rectF = ui.View->sceneRect(); //Scene的矩形区
ui.LabSceneRect->setText(QString::asprintf("QGraphicsView::sceneRect=(Left,Top,Width,Height)=%.0f,%.0f,%.0f,%.0f",
rectF.left(), rectF.top(), rectF.width(), rectF.height()));
}
构造Graphics View的各项:
//构造Graphics View的各项
void sample8_4QGraphicsView::iniGraphicsSystem()
{
QRectF rect(-200, -100, 400, 200);//左上角坐标,宽度,高度
scene = new QGraphicsScene(rect); //scene逻辑坐标系定义
ui.View->setScene(scene);
//画一个矩形框,大小等于scene
QGraphicsRectItem *item = new QGraphicsRectItem(rect); //矩形框正好等于scene的大小
item->setFlags(QGraphicsItem::ItemIsSelectable //可选,可以有焦点,但是不能移动
| QGraphicsItem::ItemIsFocusable);
QPen pen;
pen.setWidth(2);
item->setPen(pen);
//item->setPos(500,0);//缺省位置在scene的(0,0)
scene->addItem(item);
//一个位于scene中心的椭圆,测试局部坐标
QGraphicsEllipseItem *item2 = new QGraphicsEllipseItem(-100, -50, 200, 100); //矩形框内创建椭圆,绘图项的局部坐标,左上角(-100,-50),宽200,高100
item2->setPos(0, 0);//设置椭圆中心位置
item2->setBrush(QBrush(Qt::blue));
item2->setFlags(QGraphicsItem::ItemIsMovable //可移动
| QGraphicsItem::ItemIsSelectable //可选择
| QGraphicsItem::ItemIsFocusable); //可获得焦点
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();
//item->setSelected(true);
//ui.View->setDragMode(QGraphicsView::RubberBandDrag);
}
运行结果如下:
"QWGraphicsView.cpp" 文件代码如下:
#include "QWGraphicsView.h"
#include <QMouseEvent>
#include <QPoint>
QWGraphicsView::QWGraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
}
QWGraphicsView::~QWGraphicsView()
{
}
//鼠标移动事件
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);
}
"sample8_4QGraphicsView.cpp" 文件代码如下:
#include "sample8_4QGraphicsView.h"
#include "ui_sample8_4QGraphicsView.h"
#include <QGraphicsEllipseItem>
//解决QT中中文显示乱码问题
#pragma execution_character_set("utf-8")
sample8_4QGraphicsView::sample8_4QGraphicsView(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
labViewCord = new QLabel("View 坐标:");
labViewCord->setMinimumWidth(150);
ui.statusBar->addWidget(labViewCord);
labSceneCord = new QLabel("Scene 坐标:");
labSceneCord->setMinimumWidth(150);
ui.statusBar->addWidget(labSceneCord);
labItemCord = new QLabel("Item 坐标:");
labItemCord->setMinimumWidth(150);
ui.statusBar->addWidget(labItemCord);
ui.View->setCursor(Qt::CrossCursor);
ui.View->setMouseTracking(true);
ui.View->setDragMode(QGraphicsView::RubberBandDrag);
QObject::connect(ui.View, SIGNAL(mouseMovePoint(QPoint)),
this, SLOT(on_mouseMovePoint(QPoint)));
QObject::connect(ui.View, SIGNAL(mouseClicked(QPoint)),
this, SLOT(on_mouseClicked(QPoint)));
iniGraphicsSystem();
}
//鼠标移动事件,point是 GraphicsView的坐标,物理坐标
void sample8_4QGraphicsView::on_mouseMovePoint(QPoint point)
{
labViewCord->setText(QString::asprintf("View 坐标:%d,%d", point.x(), point.y()));
QPointF pointScene = ui.View->mapToScene(point); //转换到Scene坐标
labSceneCord->setText(QString::asprintf("Scene 坐标:%.0f,%.0f", pointScene.x(), pointScene.y()));
}
//鼠标单击事件
void sample8_4QGraphicsView::on_mouseClicked(QPoint point)
{
QPointF pointScene = ui.View->mapToScene(point); //转换到Scene坐标
QGraphicsItem *item = NULL;
item = scene->itemAt(pointScene, ui.View->transform()); //获取光标下的绘图项
if (item != NULL) //有绘图项
{
QPointF pointItem = item->mapFromScene(pointScene); //转换为绘图项的局部坐标
labItemCord->setText(QString::asprintf("Item 坐标:%.0f,%.0f", pointItem.x(), pointItem.y()));
}
}
//构造Graphics View的各项
void sample8_4QGraphicsView::iniGraphicsSystem()
{
QRectF rect(-200, -100, 400, 200);//左上角坐标,宽度,高度
scene = new QGraphicsScene(rect); //scene逻辑坐标系定义
ui.View->setScene(scene);
//画一个矩形框,大小等于scene
QGraphicsRectItem *item = new QGraphicsRectItem(rect); //矩形框正好等于scene的大小
item->setFlags(QGraphicsItem::ItemIsSelectable //可选,可以有焦点,但是不能移动
| QGraphicsItem::ItemIsFocusable);
QPen pen;
pen.setWidth(2);
item->setPen(pen);
//item->setPos(500,0);//缺省位置在scene的(0,0)
scene->addItem(item);
//一个位于scene中心的椭圆,测试局部坐标
QGraphicsEllipseItem *item2 = new QGraphicsEllipseItem(-100, -50, 200, 100); //矩形框内创建椭圆,绘图项的局部坐标,左上角(-100,-50),宽200,高100
item2->setPos(0, 0);//设置椭圆中心位置
item2->setBrush(QBrush(Qt::blue));
item2->setFlags(QGraphicsItem::ItemIsMovable //可移动
| QGraphicsItem::ItemIsSelectable //可选择
| QGraphicsItem::ItemIsFocusable); //可获得焦点
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();
//item->setSelected(true);
//ui.View->setDragMode(QGraphicsView::RubberBandDrag);
}
//窗口变化大小时的事件
void sample8_4QGraphicsView::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
//Graphics View坐标,左上角总是(0,0),宽度=,长度=
ui.labViewSize->setText(QString::asprintf("Graphics View坐标,左上角总是(0,0),宽度=%d,高度=%d",
ui.View->width(), ui.View->height()));
QRectF rectF = ui.View->sceneRect(); //Scene的矩形区
ui.LabSceneRect->setText(QString::asprintf("QGraphicsView::sceneRect=(Left,Top,Width,Height)=%.0f,%.0f,%.0f,%.0f",
rectF.left(), rectF.top(), rectF.width(), rectF.height()));
}
"main.cpp" 文件代码如下:
#include "sample8_4QGraphicsView.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
sample8_4QGraphicsView w;
w.show();
return a.exec();
}
《Qt5/6 C++开发指南》