文章目录
- 基础夯实:
- 效果展示:
- 一、目标:
- 二、遇到的问题
- 三、实例代码
- customgraphicsview.h
- customgraphicsview.cpp
- mainwindow.h
- mainwindow.cpp
- mian.cpp
基础夯实:
在Qt框架中,QGraphicsView 是一个非常强大的控件,用于显示 QGraphicsScene 中的图形项(QGraphicsItem)。这个控件提供了滚动和缩放视图的功能,使得用户能够查看和操作复杂的图形场景。QGraphicsView 和 QGraphicsScene 的组合是Qt中用于二维图形显示的推荐方式,因为它们提供了高度的灵活性和强大的功能。
QGraphicsView
QGraphicsView 提供了视图窗口,用户通过这个窗口来查看和操作 QGraphicsScene 中的图形项。它支持缩放、平移以及多种渲染选项。QGraphicsView 并不直接存储图形项;相反,它仅仅是一个展示窗口,所有的图形项都存储在与之关联的 QGraphicsScene 中。
QGraphicsScene
QGraphicsScene 是一个用于存储和管理图形项的容器。你可以向场景中添加、移动、删除或修改图形项。场景本身不直接进行渲染;渲染工作由视图(QGraphicsView)完成。
鼠标事件
在Qt中,你可以通过重写控件的鼠标事件处理函数来响应用户的鼠标动作。对于 QGraphicsView 来说,如果你想要处理鼠标事件(如点击、拖动等),你通常需要处理这些事件在 QGraphicsScene 中的图形项上,而不是直接在 QGraphicsView 上。
重写图形项的鼠标事件处理函数:
mousePressEvent(QGraphicsSceneMouseEvent *event):处理鼠标按下事件。
mouseMoveEvent(QGraphicsSceneMouseEvent *event):处理鼠标移动事件(如果鼠标被按下并拖动)。
mouseReleaseEvent(QGraphicsSceneMouseEvent *event):处理鼠标释放事件。
将事件传递给图形项:
QGraphicsView 默认会将鼠标事件传递给场景中的图形项。如果图形项对事件进行了处理(即返回了true),则事件不会继续传播。如果图形项没有处理事件,事件可能会继续传播给视图或其他对象。
绘图事件
在Qt中,绘图通常是通过重写 paintEvent(QPaintEvent *event) 函数来完成的。然而,在 QGraphicsView 架构中,你通常不会直接在 QGraphicsView 上进行绘图。相反,你会在 QGraphicsScene 中创建和管理图形项,这些图形项会在需要时被渲染到视图上。
如果你需要自定义图形项的绘制行为,你应该继承 QGraphicsItem 并重写其 paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 函数。这个函数提供了绘制图形项所需的 QPainter 对象和其他信息。
总结来说,QGraphicsView 提供了展示 QGraphicsScene 中图形项的视图窗口,并允许用户通过鼠标事件与之交互。绘图则是在 QGraphicsScene 中的图形项上进行的,通过重写这些图形项的 paint 方法来实现。
如果不清楚鼠标事件和QGraphicsView控件的,可以参考一下文档:
鼠标学习链接
[控件学习链接]
效果展示:
提示:如果你也想实现上图中的效果,欢迎继续阅读
一、目标:
需求:在QGraphicsView控件上面进行绘图,鼠标事件无法在控件上实现点击,拖动,释放的鼠标事件,但是需要在控件上进行绘图,就离不开鼠标事件。所以记录本文,以及我的实例,供大家参考学习:
二、遇到的问题
一开始使用了事件分发器,事件过滤器等操作,但是我并没有成功,最终使用了自定义信号,对原来的QGraphicsView控件进行了重写,最终实现了,在图片上显示矩形移动框和直线。暂时未实现的功能:不能把图形绘制到照片上,如果后面实现了,会继续更新,如果你对自定义控件和函数重写不太熟悉,可以查找资料,也可以看一下我之前的文章
三、实例代码
customgraphicsview.h
#ifndef CUSTOMGRAPHICSVIEW_H
#define CUSTOMGRAPHICSVIEW_H
#include <QGraphicsView>
#include <QPointF>
#include <QMouseEvent>
class CustomGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
enum DrawMode { RectMode, LineMode };
explicit CustomGraphicsView(QWidget *parent = nullptr);
void setDrawMode(DrawMode mode);
signals:
void mouseClicked(const QPointF &pos);
void mouseMoved(const QPointF &pos);
void mouseReleased(const QPointF &pos);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
DrawMode currentDrawMode;
bool isDrawing = false;
QPointF startPoint;
QGraphicsRectItem *rectItem = nullptr;
QGraphicsLineItem *lineItem = nullptr;
// 辅助函数,用于清理线条
void clearLineItem();
};
#endif // CUSTOMGRAPHICSVIEW_H
customgraphicsview.cpp
#include "CustomGraphicsView.h"
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QMouseEvent>
CustomGraphicsView::CustomGraphicsView(QWidget *parent)
: QGraphicsView(parent)
{
}
void CustomGraphicsView::setDrawMode(DrawMode mode)
{
currentDrawMode = mode;
// 清理之前可能存在的线条
clearLineItem();
}
void CustomGraphicsView::clearLineItem()
{
if (lineItem && scene()) {
scene()->removeItem(lineItem);
delete lineItem;
lineItem = nullptr;
}
}
void CustomGraphicsView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
isDrawing = true;
startPoint = mapToScene(event->pos());
// 清理之前可能存在的线条或矩形
clearLineItem();
if (rectItem) {
scene()->removeItem(rectItem);
delete rectItem;
rectItem = nullptr;
}
}
emit mouseClicked(event->pos());
QGraphicsView::mousePressEvent(event);
}
void CustomGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if (isDrawing) {
QPointF endPoint = mapToScene(event->pos());
if (currentDrawMode == RectMode) {
QPointF topLeft = QPointF(qMin(startPoint.x(), endPoint.x()), qMin(startPoint.y(), endPoint.y()));
QPointF bottomRight = QPointF(qMax(startPoint.x(), endPoint.x()), qMax(startPoint.y(), endPoint.y()));
QRectF rect(topLeft, bottomRight);
if (!rectItem) {
rectItem = scene()->addRect(rect, QPen(Qt::red), QBrush(Qt::NoBrush));
} else {
rectItem->setRect(rect);
}
} else if (currentDrawMode == LineMode) {
if (!lineItem) {
lineItem = scene()->addLine(startPoint.x(), startPoint.y(), endPoint.x(), endPoint.y(), QPen(Qt::blue));
} else {
lineItem->setLine(startPoint.x(), startPoint.y(), endPoint.x(), endPoint.y());
}
}
}
emit mouseMoved(event->pos());
}
void CustomGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && isDrawing) {
isDrawing = false;
// 如果需要,可以在这里处理矩形或线条的最终状态
emit mouseReleased(event->pos());
}
QGraphicsView::mouseReleaseEvent(event);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "CustomGraphicsView.h"
#include <QPixmap>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onMouseClicked(const QPointF &pos);
void onMouseMoved(const QPointF &pos);
void onMouseReleased(const QPointF &pos);
void on_pushButton_paint_rect_clicked();
void on_pushButton_paint_line_clicked();
private:
Ui::MainWindow *ui;
CustomGraphicsView *customGraphicsView;
QPixmap pixmap;
QGraphicsScene *scene;
QGraphicsPixmapItem *pixmapItem;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsRectItem>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, scene(new QGraphicsScene(this))
, pixmapItem(nullptr)
{
ui->setupUi(this);
pixmap.load(":/new/prefix1/24.jpg");
pixmapItem = new QGraphicsPixmapItem(pixmap);
scene->addItem(pixmapItem);
scene->setSceneRect(0, 0, 901, 504);
ui->graphicsView->setScene(scene);
// 注意这里连接时使用了 QPointF
connect(ui->graphicsView, &CustomGraphicsView::mouseClicked, this, &MainWindow::onMouseClicked);
connect(ui->graphicsView, &CustomGraphicsView::mouseMoved, this, &MainWindow::onMouseMoved);
connect(ui->graphicsView, &CustomGraphicsView::mouseReleased, this, &MainWindow::onMouseReleased);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onMouseClicked(const QPointF &pos) {
QString text = QString("Mouse clicked at: (%1, %2)").arg(pos.x()).arg(pos.y());
ui->mouse_press->setText(text);
qDebug() << "Mouse clicked at:" << pos;
}
void MainWindow::onMouseMoved(const QPointF &pos) {
QString text = QString("Mouse moved to: (%1, %2)").arg(pos.x()).arg(pos.y());
ui->mouse_move->setText(text);
qDebug() << "Mouse moved to:" << pos;
}
void MainWindow::onMouseReleased(const QPointF &pos) {
QString text = QString("Mouse released at: (%1, %2)").arg(pos.x()).arg(pos.y());
ui->mouse_release->setText(text);
qDebug() << "Mouse released at:" << pos;
}
void MainWindow::on_pushButton_paint_rect_clicked()
{
ui->graphicsView->setDrawMode(CustomGraphicsView::RectMode);
}
void MainWindow::on_pushButton_paint_line_clicked()
{
ui->graphicsView->setDrawMode(CustomGraphicsView::LineMode);
}
mian.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}