QGraphicsView通过鼠标操作来绘制图元

这篇具有很好参考价值的文章主要介绍了QGraphicsView通过鼠标操作来绘制图元。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Visio和MindManager等类似的图元操作软件中,很多时候我们会通过鼠标操作来添加自定义的图元。这里就介绍一下如何在QT的图形视图框架中通过鼠标绘制来添加图元。
在实现的时候我们先添加一个自定义图元用来响应鼠标操作,自定义图元的实现如下所示.

绘制辅助图元

辅助图元类似于标尺线,用来标记用户鼠标框选的范围和位置。实现如下:

//canvasitembase.h
#ifndef _CANVASE_ITEM_BASE_
#define _CANVASE_ITEM_BASE_

#include <QObject>
#include <QGraphicsItem>
#include <QPixmap>
#include <QGraphicsObject>

class CanvaseItemBase : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    CanvaseItemBase(QGraphicsItem* parentItem = nullptr);

public:
    //修改图元尺寸
    void set_item_size(int width,int height);
    void get_item_size(int& width,int& height);

protected:
    //边界矩形
    QRectF boundingRect() const override;
    //绘制事件
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) final;
    //获取形状
    QPainterPath shape() const override;

    //鼠标事件
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;

    QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;

    //自定义元素绘制
    virtual void customPaint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    //获取自定义绘制所需要的矩形
    QRectF getCustomRect(void) const;


private:
    //图元的宽和高
    int m_rect_width = 0;
    int m_rect_height = 0;

    // 画笔设置
    QColor m_cPenColor;
    int m_nPenWidth = 1;
    // 画刷设置
    QColor m_cBrushColor;
};
#endif

//canvasitembase.cpp
#include "canvasitembase.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QVector2D>
#include <QVector3D>

#define PI 3.14159265358979

CanvaseItemBase::CanvaseItemBase(QGraphicsItem* parentItem)
    :QGraphicsItem(parentItem)
    ,m_cPenColor(255, 0, 0)
    ,m_cBrushColor(200, 100, 100)
{
    //设置图元可以选中
    this->setFlag(QGraphicsItem::ItemIsSelectable, false);
    m_rect_width = 0;
    m_rect_height = 0;
}


void CanvaseItemBase::set_item_size(int width, int height)
{
    m_rect_width = width;
    m_rect_height = height;
}

void CanvaseItemBase::get_item_size(int &width, int &height)
{
    width = m_rect_width;
    height = m_rect_height;
}

QRectF CanvaseItemBase::boundingRect() const
{
    QRectF rectF = getCustomRect();
    return rectF;
}

void CanvaseItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter->setRenderHint(QPainter::TextAntialiasing, true);

    // 自定义绘制
    customPaint(painter, option, widget);
}

QPainterPath CanvaseItemBase::shape() const
{
    QPainterPath path;
    path.addRect(boundingRect());

    return path;
}

void CanvaseItemBase::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    return QGraphicsItem::mousePressEvent(event);
}

void CanvaseItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    return QGraphicsItem::mouseMoveEvent(event);
}

void CanvaseItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    return QGraphicsItem::mouseReleaseEvent(event);
}

QVariant CanvaseItemBase::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if (change == QGraphicsItem::ItemSelectedChange)
        prepareGeometryChange();

    return QGraphicsItem::itemChange(change, value);
}


void CanvaseItemBase::customPaint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen;
    pen.setWidth(m_nPenWidth);
    pen.setColor(m_cPenColor);
    pen.setStyle(Qt::DashLine);
    pen.setWidth(2);
    painter->setPen(pen);

    QRectF itemRect = this->getCustomRect();
    QRectF outLintRect = itemRect;
    if((m_rect_width == 0) ||(m_rect_width == 0))
    {
        painter->setCompositionMode(QPainter::CompositionMode_Clear);
        painter->eraseRect(outLintRect);
        return;
    }
    else
    {
        painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
        painter->drawRect(outLintRect);
    }
}

QRectF CanvaseItemBase::getCustomRect(void) const
{
   return QRectF(0,0,m_rect_width,m_rect_height);
}

在视图中当鼠标框选范围发生变化的时候,自定义图元会通过绘制红色的虚线框来标记鼠标的框选范围。

自定义视图

通过重写QGraphicsView,我们来响应对应的鼠标键盘消息,从而实现对应的绘制操作,自定义视图类的实现如下所示:

//mygraphicsview.h
#ifndef _MY_GRAPHICS_VIEW_H_
#define _MY_GRAPHICS_VIEW_H_

#include <QGraphicsView>
#include "canvasitembase.h"
#include <QGraphicsScene>
#include <QMouseEvent>
#include <QResizeEvent>


class MyGraphicsView : public QGraphicsView
{
    Q_OBJECT

public:
    explicit MyGraphicsView(QWidget *parent = nullptr);
    ~MyGraphicsView();

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void resizeEvent(QResizeEvent* event);

private:
    //绘制辅助图元
    CanvaseItemBase* m_custom_item;

    //主场景
    QGraphicsScene m_main_scene;
    //鼠标起始点和结束点
    QPoint m_start_point;
    QPoint m_end_point;
    //鼠标左键是否按下
    bool m_is_leftbtn_pressed = false;
};

#endif
//mygraphicsview.cpp
#include "mygraphicsview.h"

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

    //屏蔽显示滚动条
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //添加自定义
    m_custom_item  = new CanvaseItemBase();
    m_main_scene.addItem(m_custom_item);
    this->setScene(&m_main_scene);

    //跟踪鼠标移动
    this->setMouseTracking(true);

    int view_width = this->width();
    int view_height = this->height();
    this->setSceneRect(-0.5*view_width,-0.5*view_height,view_width,view_height);
}

MyGraphicsView::~MyGraphicsView()
{

}

void MyGraphicsView::mousePressEvent(QMouseEvent *event)
{
    QGraphicsView::mousePressEvent(event);
    if(event->button() == Qt::LeftButton)
    {
        m_start_point = m_end_point = event->pos();
        QList<QGraphicsItem*> items = this->items(m_end_point);
        //依据鼠标点击的控件位置设置元素的位置
        if(items.empty())
        {
            m_is_leftbtn_pressed = true;
            //将控件坐标映射到场景坐标
            QPointF view_point = this->mapToScene(m_start_point);
            m_custom_item->setPos(view_point);
            m_custom_item->set_item_size(0,0);
            m_custom_item->update();
            this->viewport()->update();
        }
    }
    //右键添加图元
    else if(event->button() == Qt::RightButton)
    {
        int width,height;
        m_custom_item->get_item_size(width,height);
        QPointF scene_pos = m_custom_item->scenePos();
        QGraphicsRectItem* rect_item = new QGraphicsRectItem(scene_pos.x(),scene_pos.y(),width,height);
        m_main_scene.addItem(rect_item);
    }
}

void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
    //鼠标移动过程中计算元素的宽高并更新显示
    if(m_is_leftbtn_pressed)
    {
        m_end_point = event->pos();
        int width = m_end_point.x() - m_start_point.x();
        int height = m_end_point.y() - m_start_point.y();
        m_custom_item->set_item_size(width,height);
        m_custom_item->update();
        this->viewport()->update();
    }
    this->update();
    QGraphicsView::mouseMoveEvent(event);
}

void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        if(m_start_point != m_end_point)
        {
            m_custom_item->update();
        }
        m_is_leftbtn_pressed = false;
    }
    QGraphicsView::mouseReleaseEvent(event);
}

void MyGraphicsView::resizeEvent(QResizeEvent *event)
{
    //将场景和控件完全重合,这样坐标就一一对应了
    int view_width = this->width();
    int view_height = this->height();
    this->setSceneRect(-0.5*view_width,-0.5*view_height,view_width,view_height);
}

添加了自定义视图之后,我们就可以通过鼠标操作来添加自定义图元了。鼠标在视图上左键框选一个范围,然后松开鼠标左键点击鼠标右键便可以添加一个对应范围内的图元元素了。

示例效果图

使用效果如下图所示:
qgraphicsview鼠标事件,QT,qt,开发语言,c++,图形视图框架文章来源地址https://www.toymoban.com/news/detail-535718.html

到了这里,关于QGraphicsView通过鼠标操作来绘制图元的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QGraphicsView中重写鼠标事件实现图片的移动

            本文讲的是如何在PyQt5的组件QGraphicsView中重写鼠标事件实现图片的移动。         PyQt5作为强大的GUI编程工具,免不了会拿来做一些图片的显示和处理问题,有的会使用QPainter作为动态显示图片的工具,QLabel是显示静态图片的主推。但是我在工作中遇到了超大

    2023年04月14日
    浏览(38)
  • QT QGraphicsView 在鼠标点击处进行放大缩小

    一、前段时间在用QGraphicsView对图元进行放大缩小时,发现图形总是越来越跑偏,无法像地图中那样,点击哪里就能放大哪个地方。 如下所示:此时放大缩小的焦点并不在鼠标位置 方法,使用QGraphicsView类的设置属性函数.在构造函数中增加下面两个函数即可。 此时以鼠标为中

    2024年02月16日
    浏览(34)
  • QGraphicsView如何使图片以鼠标为中心进行放缩

    顺带说一句,下面的代码放在了一个继承了QMainWindow的自定义class里面,这个类包含着一个QGraphicsView部件,所有以下的代码都会以为处在类中而出现对应的首行缩进。 因为QGraphicsView是从Qt整个改过来的,自然包含了所有的部件,其中就有所用到的三句话: self.ui.graphicsView.se

    2024年02月13日
    浏览(27)
  • QGraphicsView 如何实现百度地图按照鼠标点进行放大缩小效果

    前段时间用了QGraphicsView做了一些工作,然而如何实现QGraphicsView的放大缩小的效果也很简单,照鼠标某一点进行缩放,仅靠以下代码对view进行缩放会导致view上的item在放大缩小的过程中跑偏了。 我们看一下仅靠以上代码实现的放大缩小的效果。 从下图中我们看到把图中小矩形

    2024年02月05日
    浏览(43)
  • 【[Qt]基于QGraphicsView的图像显示控件,支持放大、缩小、鼠标拖动】

    ImageViewer.h文件 ImageViewer.cpp 文件 具体使用代码如下 1、初始化类对象,并加入界面布局中 2、打开图像,并加载到控件中 3、从控件中卸载图片 源码链接:https://download.csdn.net/download/xiaohuihuihuige/87239431 百度云: 链接:https://pan.baidu.com/s/1W-KUlIKUFAktUKFin63N0g 提取码:4g8a

    2024年02月11日
    浏览(42)
  • 【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件

    说明 在使用Qt的图形视图框架实现功能时,一般会在其基础上进行自定义功能实现。 如:滚轮对场景的缩放,鼠标拖动场景中的项,以及可以在场景中进行右键操作等。 示例 myitem 为自定义QGraphicsItem,实现了边框、重绘事件、鼠标悬停、按键、右键菜单等功能。 myitem.h myi

    2024年02月04日
    浏览(39)
  • QGraphicsView 显示图片

    QGraphicsView 是 PyQt6 里负责显示图形的组件,搭配 QGraphicsScene 和 QtGui.QPixmap() 就可以显示图片,这篇教学会介绍如何在 PyQt6 窗口里加入 QGraphicsView 组件并显示图片。 快速预览: QGraphicsView 显示图片 改变图片尺寸 设定图片位置 显示多张图片 建立 PyQt6 窗口物件后, 透过 QtWidg

    2023年04月25日
    浏览(26)
  • QGraphicsView 实例3地图浏览器

    主要介绍Graphics View框架,实现地图的浏览、放大、缩小,以及显示各个位置的视图、场景和地图坐标 效果图:  mapwidget.h  mapwidget.cpp

    2024年02月12日
    浏览(27)
  • Qt中QGraphicsView总体架构学习

    前段时间学习了下如何在QGraphicsView架构中绘制刻度尺,主要是与OnPainter中进行比较的,那么今天就来详细讲解下我对QGraphicsView框架的认知吧~ 最近一段时间想学习下,如果我有不正确的,欢迎留言探讨哟~ 使用过OnPainter绘制过图形的,QPainter绘制需要在绘制设备的paintEvent()事

    2024年02月02日
    浏览(27)
  • QGraphicsView 如何让图形大小适配窗口

    setSceneRect是一个Qt中的函数,用于设置QGraphicsView中的场景矩形(QRectF)。 QGraphicsView是一个用于显示和编辑图形场景的控件,而setSceneRect函数用于设置场景矩形,即指定场景的可视区域的大小和位置。具体来说,它的作用有以下几个方面: 定义场景的大小:通过设置场景矩形

    2024年01月24日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包