精华内容
下载资源
问答
  • 绘制或导入的QGraphicsItem可能会很大或很小,我们想要根据现实窗口的大小自适应显示item,基于个人对QGraphics Scene、Graphics Item、Graphics View关系[^1]的理解,发现一种方法使用可以解决需求。
  • qt5工程,实现类似于图片浏览器功能,QGraphicsView(平移/缩放/旋转);参考某大神的做法;
  • QGraphicsView截图.zip

    2020-05-07 22:01:39
    QT 通过图形视图框架(支持场景(Scene)中的图元(Item)进行精确的双精度交互功能。图元可以处理键盘事件、鼠标按下、移动、释放和双击事件,同时也能跟踪鼠标移动)鼠标左键点击 实现截图功能
  • 支持图形的绘制,移动与拖拽、放大缩小、旋转、复制粘贴、撤销重做;绘制图形包括矩形、多边形、椭圆、直线、曲线等
  • 画图软件,基于QGraphicsView实现,可画直线,矩形,椭圆,圆角矩形,不规则多边形,曲线等等基本功能,并且可编辑这些图形,代码封装完毕,可简单移植到项目中使用。
  • 在使用QGraphicsView过程中,有时候我们需要对view进行缩放,但是对于一般正常的加入view中的item都会随着view的大小变化而变化,但是如果我们想让某些item不随view的缩放进行改变怎么办呢?详情见博客:...
  • QT 控件QGraphicsView的简单用法,包含头文件和cpp,函数调用参考README.txt
  • 实现qt QGraphicsView放大缩小功能的类,不用继承QGraphicsView,只需要在该类中设置要实现放大缩小的QGraphicsView对象即可。
  • 在用Qt做窗口透明处理时是接收不到鼠标事件的,想要在窗口透明的情况下去接收鼠标消息还需要依靠QGraphicsScene与QGraphicsView,当然Linux与windows还是有点区别的,具体看代码
  • Qt绘图 QGraphicsView

    2017-07-06 19:16:13
    使用 QGraphicsView、QGraphicsScene、QGraphicsItem进行简单的缩放,移动,旋转
  • QGraphicsView画折线图Qt计算线段交点QGraphicsItem得简单使用
  • 地图浏览器 QGraphicsView,QGraphicsScene
  • QGraphicsView.zip

    2019-08-01 14:12:50
    QGraphicsView 支持拖拽缩放
  • qgraphicsview

    2014-08-10 16:04:39
    qgraphicsview封装成表格的形式,根据row 和column 来设置控件的位置
  • QGraphicsView_Demo.txt

    2020-03-31 18:21:26
    重写QGraphicsView,实现缩放,平移功能,平移时会同步QGraphicsView滚动条位置,这样不会导致移动以后和QGraphicsView的滚动条不匹配。
  • MyDropDemo
  • Qt之QGraphicsView进阶篇

    万次阅读 多人点赞 2020-04-06 15:50:35
    作者:billy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 前言 上一章节介绍了 QGraphicsView 中的基础内容,具体请参考 Qt之QGraphicsView入门篇。这一章节我们来具体了解一下 ...

    作者:billy
    版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

    前言

    上一章节介绍了 QGraphicsView 中的基础内容,具体请参考 Qt之QGraphicsView入门篇。这一章节我们来具体了解一下 GraphicsView 框架中有哪些特性。

    缩放与旋转

    QGraphicsView 通过 QGraphicsView::setMatrix() 支持和 QPainter 一样的仿射变换,通过对一个视图应用变换,你可以很容易地支持普通的导航特性如缩放与旋转。

    示例:

    #include <QApplication>
    #include <QGraphicsView>
    #include <QGraphicsScene>
    #include <QGraphicsRectItem>
    #include <QDialog>
    #include <QVBoxLayout>
    #include <QPushButton>
    
    class MyGraphicsView : public QGraphicsView	// 自定义视图类,实现对视图的缩放和旋转
    {
    public:
        MyGraphicsView() {}
    
    public slots:
        void zoomIn() { scale(1.2, 1.2); }
        void zoomOut() { scale(1/1.2, 1/1.2); }
        void rotateLeft() { rotate(-30); }
        void rotateRight() { rotate(30); }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QGraphicsScene scene;   // 定义一个场景,设置背景色为红色
        scene.setBackgroundBrush(Qt::red);
    
        QPen pen;   // 定义一个画笔,设置画笔颜色和宽度
        pen.setColor(QColor(0, 160, 230));
        pen.setWidth(10);
    
        QGraphicsRectItem *m_rectItem = new QGraphicsRectItem();   // 定义一个矩形图元
        m_rectItem->setRect(0, 0, 80, 80);
        m_rectItem->setPen(pen);
        m_rectItem->setBrush(QBrush(QColor(255, 255, 255)));
        m_rectItem->setFlag(QGraphicsItem::ItemIsMovable);
        scene.addItem(m_rectItem);      // 把矩形图元添加到场景
    
        QDialog *dialog = new QDialog(nullptr, Qt::CustomizeWindowHint | Qt::WindowTitleHint);
        dialog->setWindowOpacity(0.8);
        dialog->setWindowTitle("operation");
        dialog->setLayout(new QVBoxLayout);
        QPushButton *m_zoomInBtn = new QPushButton("zoomIn");
        QPushButton *m_zoomOutBtn = new QPushButton("zoomOut");
        QPushButton *m_rotateLeftBtn = new QPushButton("rotateLeft");
        QPushButton *m_rotateRightBtn = new QPushButton("rotateRight");
        dialog->layout()->addWidget(m_zoomInBtn);
        dialog->layout()->addWidget(m_zoomOutBtn);
        dialog->layout()->addWidget(m_rotateLeftBtn);
        dialog->layout()->addWidget(m_rotateRightBtn);
        scene.addWidget(dialog);
    
        MyGraphicsView view; // 定义一个视图,并把场景添加到视图
        view.setScene(&scene);
        view.resize(1024, 768);
        view.show();
    
        // 点击按钮实现视图的缩放和旋转
        QObject::connect(m_zoomInBtn, &QPushButton::clicked, [&]() { view.zoomIn(); });
        QObject::connect(m_zoomOutBtn, &QPushButton::clicked, [&]() { view.zoomOut(); });
        QObject::connect(m_rotateLeftBtn, &QPushButton::clicked, [&]() { view.rotateLeft(); });
        QObject::connect(m_rotateRightBtn, &QPushButton::clicked, [&]() { view.rotateRight(); });
    
        return a.exec();
    }
    

    在这里插入图片描述

    打印

    Qt中对打印的支持是有一个独立的 printsupport 模块来完成的,所以要想在程序中使用Qt的打印功能,必须先在pro文件中添加:
    QT += printsupport

    图形视图通过它的展示函数:QGraphicsScene::render() 和 QGraphicsView::render() 提供单线(single-line)打印。这些函数提供相同的API,通过将 QPainter 传递给展示函数,你可以打印场景、视图的全部或部分内容。

    场景和视图的渲染函数的不同在于 QGraphicsScene::render() 使用场景坐标,而 QGraphicsView::render() 使用视图坐标。QGraphicsScene::render() 经常用于打印未变换场景中的整块,例如一块图形数据或是打印一个文本文档。 QGraphicsView::render() 适合用于打印屏幕快照(screenshots),缺省情况下它展示视图端口中的当前内容。

    官方示例:在这里插入图片描述在这里插入图片描述

    拖拽和碰撞检测

    由于 QGraphicsView 继承自 QWidget,所以 GraphicsView 同样提供了拖拽功能。此外,GraphicsView 框架也为场景、图元提供拖拽支持。当视图接收到拖拽事件,GraphicsView 框架会将拖拽事件翻译为 QGraphicsSceneDragDropEvent 事件,再发送到场景,场景接管事件,再把事件发送到光标下接受拖拽的第一个图元

    为了在场景中获取拖拽事件,你需要重新实现QGraphicsScene::dragEnterEvent() 和在 QGraphicsItem 的子类里任何与你特定场景需要的事件处理器。items 也可以通过调用 QGraphicsItem::setAcceptDrops() 获得拖拽支持,为了处理将要进行的拖拽,你需要重新实现 dropEvent、dragdragEnterEvent、dragLeaveEvent、dropMoveEvent、mousePressEvent、mouseReleaseEvent 和 mouseMoveEvent

    为了处理碰撞时的行为,我们需要创建 QGrahicsItem 的一个子类,然后重新实现 boundingRect 和 paint。boundingRect 用于返回图元绘制所需要的估测区域,而 paint 实现实际的绘图操纵

    这里展示一个小例子,外面一圈是 colorItem 实现了拖拽,中间是个 dropItem 实现了碰撞检测。当我把某个 colorItem 拖拽并触碰到 dropItem 时,dropItem 的颜色就会变成 colorItem 的颜色。代码太多就不放了,感兴趣的小伙伴可以在最下面示例中下载源代码。

    在这里插入图片描述

    光标与工具提示

    像QWidget一样,QGraphicsItem也支持光标 QgraphicsItem::setCursor() 与工具提示 QGraphicsItem::setToolTip()。当光标进入到item的区域,光标与工具提示被 QGraphicsView 激活,通过调用 QGraphicsItem::contains()来检测。你也可以直接在视图上设置一个缺省光标 QGraphicsView::setCursor()。

    动画

    GraphicsView 框架支持多种层次的动画,使用动画框架可以很容易制作出动画。GraphicsView 框架支持的动画实现种类如下:

    • 图元需要继承自 QGraphicsObject,并且需要联结 QPropertyAnimation属性
    • 创建继承自 QObject 和 QGraphicsItem 的图元,图元可以设置自己的定时器,通过在QObject::timeEvent() 中增加步进的方式来控制动画
    • 通过调用 QGraphicsScene::advance() 来推进场景,依次调用QGraphicsItem::advance()

    OpenGL渲染

    为了使用 OpenGL 渲染,你要设置一个新的 QGLWidget 作为QGraphicsView 的视口 QGraphicsView::setViewPort()。假如你让 OpenGL 提供反锯齿功能,你需要 OpenGL 采样缓冲支持。

    QGraphicsView view;
    view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
    view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
    view.setScene(new OpenGLScene);
    view.show();
    

    Item组

    通过把一个图元做为另一个图元的孩子,可以得到图元组的大多数本质特性:所有图元会一起移动,所有变换会从父到子传递

    另外,QGraphicsItemGroup 是一个特殊的图元。为了增加和删除图元,它使用一个有用接口合并了子图元的事件处理。把一个图元加到QGraphicsItemGroup 仍会保留图元的原始位置与变换,而给一个图元重新指定父图元则会让图元根据其新的父亲重新定位。可以用QGraphicsScene::createItemGroup() 创建图元组。

    图形组件和布局

    QT4.4 通过 QGraphicsWidget 支持图形和图元布局。QGraphicsWidget 类似于 QWidget,但 QGraphicsWidget 并不从 QPaintDevice 继承,而是继承自 QGraphicsItem。QGraphicsWidget 支持事件、信号与槽、大小和策略。通过 QGraphicsLinearLayout、QGraphicsGridLayout 可以对图形组件进行布局管理。

    QGraphicsWidget 继承了 QWidget 和 QGraphicsItem 的优点,如 QWidget的样式、字体、调色板、布局方向以及 QGraphicsItem 的图形、独立精度和变换支持。

    QGraphicsLayout 是专为 QGraphicsWidget 特殊设计的第二代布局框架。QGraphicsLayout 的API类似于 QLayout。通过 QGraphicsLinearLayout 和QGraphicsGridLayout 可以管理组件与子布局。

    嵌入组件

    图形视图框架为嵌入任何组件到场景提供了无缝支持。可以嵌入简单的组件,如 QLineEdit、QPushButton,或是复杂的组件如 QTableWidget,甚至是主窗口。

    要嵌入组件到场景,只需要调用 QGraphicsScene::addWidget(),或是创建一个 QGraphicsProxyWidget 实例,手动嵌入组件。通过 QGraphicsProxyWidget,图形视图框架可以深度整合客户组件特性,如光标、工具提示、鼠标、平板和键盘事件、子组件、动画、弹拉框、组件输入焦点和激活。QGraphicsProxyWidget 甚至整合了嵌入组件的 tab 顺序,可以通过 tab 选择嵌入的组件。甚至可以嵌入一个 QGraphicsView 到场景。

    示例

    1. 拖拽和碰撞检测示例
      github 源代码下载

    2. 网上的一个3D模型示例
      github 源代码下载

    在这里插入图片描述

    更多请参考

    展开全文
  • qt例程QGraphicsview_test.7z
  • Qt之QGraphicsView实战篇

    万次阅读 多人点赞 2020-05-05 19:38:47
    前面的章节介绍了 Graphics View 绘图架构,终于到实战了,真的是千呼万唤始出来!这一章节就用 Graphics View 绘图架构来做一个绘图工具,实现一些基础图形的绘制,废话不多说先来看一下结果演示: 图形绘制介绍 ...

    作者:billy
    版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

    前言

    前面的章节介绍了 Graphics View 绘图架构,终于到实战了,真的是千呼万唤始出来!这一章节就用 Graphics View 绘图架构来做一个绘图工具,实现一些基础图形的绘制,废话不多说先来看一下结果演示:

    在这里插入图片描述

    图形绘制介绍

    我们知道简单的几何图形,只要确定两个点就可以完成绘制。比如要画一个圆,一个点可以定为圆心,由另一个点则可以计算出到圆心的距离,即圆的为半径,确定了圆心和半径那么这个圆就完成了。

    同样的道理,椭圆、正方形、矩形、圆端矩形,也可以由一个中心点和一个可拖动来改变图形的形状和大小的点(这里我们管这个点叫边缘点)来确定,边缘点的坐标可以直接用来确定图形的宽度和高度。

    而在饼、和弦中,边缘点不仅仅是用来决定图形的宽度和高度,还需要用来确定角度(与X轴正方向的夹角)。

    最麻烦的是多边形,因为每点击一下就需要绘制一个点并且完成连线,所以需要把每个点的坐标从场景传递到图形,然后在图形中完成绘制。

    自定义功能图元 - 点

    点依附于图形之上,所以构造函数中需要传入一个图形,代表这个点在这个图形上,并且需要初始化点的坐标和类型;

    class BPointItem : public QObject, public QAbstractGraphicsShapeItem
    {
        Q_OBJECT
    
    public:
        enum PointType {
            Center = 0, // 中心点
            Edge,       // 边缘点(可拖动改变图形的形状、大小)
            Special     // 特殊功能点
        };
    
        BPointItem(QAbstractGraphicsShapeItem* parent, QPointF p, PointType type);
    
        QPointF getPoint() { return m_point; }
        void setPoint(QPointF p) { m_point = p; }
    
    protected:
        virtual QRectF boundingRect() const override;
    
        virtual void paint(QPainter *painter,
                           const QStyleOptionGraphicsItem *option,
                           QWidget *widget) override;
    
        virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    
    private:
        QPointF m_point;
        PointType m_type;
    };
    

    根据类型不同,绘制的形状也不同。中心点是一个圆,并且光标是 OpenHandCursor,而其他类型的点则是一个正方形,光标是 PointingHandCursor

    当我们移动点的时候,如果是中心点则会整个图形一起移动,而移动边缘点的时候会根据边缘点的坐标来动态改变图形的形状,这里代码比较多就不贴了。

    BPointItem::BPointItem(QAbstractGraphicsShapeItem* parent, QPointF p, PointType type)
        : QAbstractGraphicsShapeItem(parent)
        , m_point(p)
        , m_type(type)
    {
        this->setPos(m_point);
        this->setFlags(QGraphicsItem::ItemIsSelectable |
                       QGraphicsItem::ItemIsMovable |
                       QGraphicsItem::ItemIsFocusable);
    
        switch (type) {
        case Center:
            this->setCursor(Qt::OpenHandCursor);
            break;
        case Edge:
            this->setCursor(Qt::PointingHandCursor);
            break;
        case Special:
            this->setCursor(Qt::PointingHandCursor);
            break;
        default: break;
        }
    }
    
    QRectF BPointItem::boundingRect() const
    {
        return QRectF(-4, -4, 8, 8);
    }
    
    void BPointItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        Q_UNUSED(option);
        Q_UNUSED(widget);
        painter->setPen(this->pen());
        painter->setBrush(this->brush());
        this->setPos(m_point);
    
        switch (m_type) {
        case Center:
            painter->drawEllipse(-4, -4, 8, 8);
            break;
        case Edge:
            painter->drawRect(QRectF(-4, -4, 8, 8));
            break;
        case Special:
            painter->drawRect(QRectF(-4, -4, 8, 8));
            break;
        default: break;
        }
    }
    
    void BPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        if ( event->buttons() == Qt::LeftButton ) {
            qreal dx = event->scenePos().x() - event->lastScenePos().x();
            qreal dy = event->scenePos().y() - event->lastScenePos().y();
    
            BGraphicsItem* item = static_cast<BGraphicsItem *>(this->parentItem());
            BGraphicsItem::ItemType itemType = item->getType();
    
            switch (m_type) {
            case Center: {
                item->moveBy(dx, dy);
                this->scene()->update();
            } break;
            case Edge: {
                略...
            } break;
            case Special: {
                略...
            } break;
            default: break;
            }
        }
    }
    

    自定义图元基类

    定义了一个图元基类,每一个图元都至少需要一个中心点、一个边缘点和图元类型。重写了焦点事件,当获得焦点时会改变颜色

    class BGraphicsItem : public QObject, public QAbstractGraphicsShapeItem
    {
        Q_OBJECT
    
    public:
        enum ItemType {
            Circle = 0,         // 圆
            Ellipse,            // 椭圆
            Concentric_Circle,  // 同心圆
            Pie,                // 饼
            Chord,              // 和弦
            Rectangle,          // 矩形
            Square,             // 正方形
            Polygon,            // 多边形
            Round_End_Rectangle,// 圆端矩形
            Rounded_Rectangle   // 圆角矩形
        };
    
        QPointF getCenter() { return m_center; }
        void setCenter(QPointF p) { m_center = p; }
    
        QPointF getEdge() { return m_edge; }
        void setEdge(QPointF p) { m_edge = p; }
    
        ItemType getType() { return m_type; }
    
    protected:
        BGraphicsItem(QPointF center, QPointF edge, ItemType type);
    
        virtual void focusInEvent(QFocusEvent *event) override;
        virtual void focusOutEvent(QFocusEvent *event) override;
    
    protected:
        QPointF m_center;
        QPointF m_edge;
        ItemType m_type;
        BPointItemList m_pointList;
    
        QPen m_pen_isSelected;
        QPen m_pen_noSelected;
    };
    
    BGraphicsItem::BGraphicsItem(QPointF center, QPointF edge, ItemType type)
        : m_center(center), m_edge(edge), m_type(type)
    {
        m_pen_noSelected.setColor(QColor(0, 160, 230));
        m_pen_noSelected.setWidth(2);
        m_pen_isSelected.setColor(QColor(255, 0, 255));
        m_pen_isSelected.setWidth(2);
    
        this->setPen(m_pen_noSelected);
        this->setFlags(QGraphicsItem::ItemIsSelectable |
                       QGraphicsItem::ItemIsMovable |
                       QGraphicsItem::ItemIsFocusable);
    }
    
    void BGraphicsItem::focusInEvent(QFocusEvent *event)
    {
        Q_UNUSED(event);
        this->setPen(m_pen_isSelected);
    }
    
    void BGraphicsItem::focusOutEvent(QFocusEvent *event)
    {
        Q_UNUSED(event);
        this->setPen(m_pen_noSelected);
    }
    

    矩形

    以矩形为例来介绍一下图元,构造函数参数为中心点坐标和矩形的宽、高、类型。初始化中心点和边缘点之后即可绘制出矩形,重写 paint 函数把矩形的宽和高绑定到 m_edge 的坐标,矩形的大小就由边缘点的坐标决定,当我们拖到边缘点时只需更新 m_edge 的坐标,矩形的形状就能动态改变

    class BRectangle : public BGraphicsItem
    {
    public:
        BRectangle(qreal x, qreal y, qreal width, qreal height, ItemType type);
    
    protected:
        virtual QRectF boundingRect() const override;
    
        virtual void paint(QPainter *painter,
                           const QStyleOptionGraphicsItem *option,
                           QWidget *widget) override;
    };
    
    BRectangle::BRectangle(qreal x, qreal y, qreal width, qreal height, ItemType type)
        : BGraphicsItem(QPointF(x,y), QPointF(width/2,height/2), type)
    {
        BPointItem *point = new BPointItem(this, m_edge, BPointItem::Edge);
        point->setParentItem(this);
        m_pointList.append(point);
        m_pointList.append(new BPointItem(this, m_center, BPointItem::Center));
        m_pointList.setRandColor();
    }
    
    QRectF BRectangle::boundingRect() const
    {
        return QRectF(m_center.x() - m_edge.x(), m_center.y() - m_edge.y(), m_edge.x() * 2, m_edge.y() * 2);
    }
    
    void BRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        Q_UNUSED(option);
        Q_UNUSED(widget);
        painter->setPen(this->pen());
        painter->setBrush(this->brush());
    
        QRectF ret(m_center.x() - m_edge.x(), m_center.y() - m_edge.y(), m_edge.x() * 2, m_edge.y() * 2);
        painter->drawRect(ret);
    }
    

    自定义场景

    当我们绘制多边形时,需要每点击一下绘制点和连线。此时我们的鼠标点击事件是在场景中的,而我们需要把场景中的坐标传递到图元中,所以我们需要自定义场景来重写场景中的鼠标事件

    class BQGraphicsScene : public QGraphicsScene
    {
        Q_OBJECT
    
    public:
        BQGraphicsScene(QObject *parent = nullptr);
    
        void startCreate();
    
    protected:
        virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
    
    signals:
        void updatePoint(QPointF p, QList<QPointF> list, bool isCenter);
        void createFinished();
    
    protected:
        QList<QPointF> m_list;
        bool is_creating_BPolygon;
    };
    
    BQGraphicsScene::BQGraphicsScene(QObject *parent) : QGraphicsScene(parent)
    {
        is_creating_BPolygon = false;
    }
    
    void BQGraphicsScene::startCreate()
    {
        is_creating_BPolygon = true;
        m_list.clear();
    }
    
    void BQGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
        if (is_creating_BPolygon) {
            QPointF p(event->scenePos().x(), event->scenePos().y());
    
            switch ( event->buttons() )
            {
            case Qt::LeftButton: {
                m_list.push_back(p);
                emit updatePoint(p, m_list, false);
            } break;
            case Qt::RightButton: {
                if (m_list.size() >= 3) {
                    emit updatePoint(p, m_list, true);
                    emit createFinished();
                    is_creating_BPolygon = false;
                    m_list.clear();
                }
            } break;
            default: break;
            }
        } else {
            QGraphicsScene::mousePressEvent(event);
        }
    }
    
    void MainWindow::on_polygonBtn_clicked()
    {
        m_scene.startCreate();
        setBtnEnabled(false);
        BPolygon *m_polygon = new BPolygon(BGraphicsItem::ItemType::Polygon);
        m_scene.addItem(m_polygon);
    
        connect(&m_scene, SIGNAL(updatePoint(QPointF, QList<QPointF>, bool)), m_polygon, SLOT(pushPoint(QPointF, QList<QPointF>, bool)));
        connect(&m_scene, &BQGraphicsScene::createFinished, [=](){
            setBtnEnabled(true);
        });
    }
    

    右键弹窗修改属性

    在这里插入图片描述

    右键跳出弹窗可以重写 contextMenuEvent 函数来完成,弹窗中需要哪些控件可以自定义实现;

    void BEllipse::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
    {
        if ( !this->isSelected() )
            return;
    
        QMenu* menu = new QMenu();
        menu->setStyleSheet("QMenu { background-color:rgb(89,87,87); border: 5px solid rgb(235,110,36); }");
    
        QSpinBox* width_spinBox = new QSpinBox(menu);
        width_spinBox->setStyleSheet("QSpinBox{ width:120px; height:30px;}");
        width_spinBox->setRange(0, 1000);
        width_spinBox->setPrefix("w: ");
        width_spinBox->setSuffix(" mm");
        width_spinBox->setSingleStep(1);
        width_spinBox->setValue(2 * abs(m_edge.x()));
        connect(width_spinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int v){
            m_edge.setX(v/2);
            m_pointList.at(0)->setPoint(m_edge);
            this->hide();
            this->update();
            this->show();
        });
    
        QSpinBox* height__spinBox = new QSpinBox(menu);
        height__spinBox->setStyleSheet("QSpinBox{ width:120px; height:30px;}");
        height__spinBox->setRange(0, 1000);
        height__spinBox->setPrefix("h: ");
        height__spinBox->setSuffix(" mm");
        height__spinBox->setSingleStep(1);
        height__spinBox->setValue(2 * abs(m_edge.y()));
        connect(height__spinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int v){
            m_edge.setY(v/2);
            m_pointList.at(0)->setPoint(m_edge);
            this->hide();
            this->update();
            this->show();
        });
    
        QWidgetAction* width_widgetAction = new QWidgetAction(menu);
        width_widgetAction->setDefaultWidget(width_spinBox);
        menu->addAction(width_widgetAction);
    
        QWidgetAction* height_widgetAction = new QWidgetAction(menu);
        height_widgetAction->setDefaultWidget(height__spinBox);
        menu->addAction(height_widgetAction);
    
        menu->exec(QCursor::pos());
        delete menu;
    
        QGraphicsItem::contextMenuEvent(event);
    }
    

    更多请参考

    展开全文
  • Qt图形视图框架:QGraphicsView详解

    千次阅读 2021-05-29 13:18:38
    QGraphicsView在可滚动视口中可视化QGraphicsScene的内容。例: QGraphicsScene scene; scene.addText("Hello, world!"); QGraphicsView view(&scene); view.show(); 视图可用于可视化整个场景,或仅...

    一、描述

    QGraphicsView在可滚动视口中可视化QGraphicsScene的内容。例:

         QGraphicsScene scene;
         scene.addText("Hello, world!");
    
         QGraphicsView view(&scene);
         view.show();

    视图可用于可视化整个场景,或仅可视化其中的一部分。默认情况下,在第一次显示视图时会自动检测可视化区域(通过调用 QGraphicsScene::itemsBoundingRect())。要自己设置可视化区域矩形,可以调用 setSceneRect()。这将适当地调整滚动条的范围。请注意,尽管场景支持几乎无限大小,但滚动条的范围永远不会超过整数范围(INT_MIN、INT_MAX)。

    可以使用鼠标和键盘与场景中的项目进行交互。 QGraphicsView将鼠标和按键事件转化为场景事件,并转发到可视化的场景中。

    二、类型成员

    1、QGraphicsView::CacheModeFlag:视图的缓存模式。视图可以在QPixmap中缓存预渲染的内容,然后将其绘制到视口上。这种缓存的目的是加快渲染速度较慢的区域的总渲染时间。例如,纹理、渐变和 alpha 混合背景的渲染速度可能非常慢,尤其是转换后的视图。 每次转换视图时,缓存都会失效。滚动时,只需要部分失效。

    • QGraphicsView::CacheNone:不缓存,所有绘制都直接在视口上完成。
    • QGraphicsView::CacheBackground:启用缓存背景。

    2、QGraphicsView::DragMode:在视口上按下并拖动鼠标时视图的默认操作。

    • QGraphicsView::NoDrag:无拖拽,鼠标事件被忽略。
    • QGraphicsView::ScrollHandDrag:光标变为指向手型,拖动鼠标将滚动滚动条。 此模式在交互和非交互模式下均可使用。

    • QGraphicsView::RubberBandDrag:会出现一个橡皮筋框。拖动鼠标将设置橡皮筋框范围,所有被橡皮筋覆盖的项目都会被选中。对于非交互式视图禁用此模式。

    3、QGraphicsView::OptimizationFlag:可以启用以提高视图渲染性能的标志。默认情况下,没有设置这些标志。请注意,设置标志通常会产生副作用,并且此效果可能在绘画设备和平台之间有所不同。

    • QGraphicsView::DontSavePainterState:渲染时,视图会在渲染背景或前景以及渲染每个图形项时保存画家状态(QPainter::save())。
    • QGraphicsView::DontAdjustForAntialiasing:禁用视图对暴露区域的抗锯齿自动调整。在QGraphicsItem::boundingRect() 边界上呈现抗锯齿线的图形项最终可能会在外部呈现部分线条。为了防止呈现伪像,视图将所有暴露区域在所有方向上扩大2个像素。 如果启用此标志,视图将不再执行这些调整,从而最小化需要重绘的区域,从而提高性能。一个常见的副作用是使用抗锯齿绘制的项目在移动时会在场景中留下绘画痕迹。

    4、QGraphicsView::ViewportAnchor:当用户调整视图大小或转换视图时视图可以使用的锚点。

    • QGraphicsView::NoAnchor:没有锚点,即视图使场景的位置保持不变。
    • QGraphicsView::AnchorViewCenter:视图中心的场景点用作锚点。
    • QGraphicsView::AnchorUnderMouse:鼠标下方的点用作锚点。

    5、QGraphicsView::ViewportUpdateMode:场景内容更改时如何更新视口。

    • QGraphicsView::FullViewportUpdate:当场景的任何可见部分发生变化或重新曝光时,视图将更新整个视口。这是不支持部分更新的视口(例如 QOpenGLWidget)以及需要禁用滚动优化的视口的首选更新模式。
    • QGraphicsView::MinimalViewportUpdate:视图将确定需要重绘的最小视区区域,通过避免重绘未更改的区域来最小化绘制时间。 这是视图的默认模式。虽然这种方法总体上提供了最好的性能,但如果场景中有许多小的可见变化,视图最终可能会花费更多的时间来寻找最小化区域的方法而不是绘制。
    • QGraphicsView::SmartViewportUpdate:视图将尝试通过分析需要重绘的区域来寻找最佳更新模式。
    • QGraphicsView::BoundingRectViewportUpdate:将重新绘制视口中所有更改的边界矩形。这种模式的优点是视图只搜索一个区域的变化,最大限度地减少确定需要重绘什么的时间。缺点是没有改变的区域也需要重新绘制。
    • QGraphicsView::NoViewportUpdate:视图永远不会在场景改变时更新它的视口,用户应控制所有更新。此模式禁用视图中的所有(可能很慢)图形项可见性测试,适用于需要固定帧速率或视口以其他方式从外部更新的场景。

    三、属性成员

    1、alignment : Qt::Alignment

    当整个场景可见时(即没有可见的滚动条(视图范围 >= 场景范围)),此属性保持视图中场景的对齐方式。对齐方式将决定场景在视图中的渲染位置。例如,如果对齐方式是Qt::AlignCenter,这是默认的,场景将在视图中居中,如果对齐方式是(Qt::AlignLeft | Qt::AlignTop),场景将在顶部渲染 - 视图的左角。

    2、backgroundBrush : QBrush 

    此属性保存场景的背景画刷。它用于覆盖场景自身的背景。要为视图提供自定义背景绘图,可以改为重新实现drawBackground()。默认为Qt::NoBrush模式的画刷。

    3、cacheMode : CacheMode 

    缓存背景模式。如:

         QGraphicsView view;
         view.setBackgroundBrush(QImage(":/images/backgroundtile.png"));
         view.setCacheMode(QGraphicsView::CacheBackground);

    4、dragMode : DragMode

    5、foregroundBrush : QBrush

    此属性保存场景的前景画刷。它用于覆盖场景自身的前景。要为视图提供自定义前景绘图,可以改为重新实现drawForeground()。默认为Qt::NoBrush模式的画刷。

     6、interactive : bool

    视图是否允许场景交互。如果启用,此视图将设置为允许场景交互。否则不允许交互,并且将忽略任何鼠标或键事件(即,它将充当只读视图)。默认为 true。

    7、optimizationFlags : OptimizationFlags 

    8、renderHints : QPainter::RenderHints

    这些提示用于在绘制每个可见图形项之前初始化QPainter。默认情况下启用QPainter::TextAntialiasing。例:

         QGraphicsScene scene;
         scene.addRect(QRectF(-10, -10, 20, 20));
    
         QGraphicsView view(&scene);
         view.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
         view.show();

    9、resizeAnchor : ViewportAnchor

    调整视图大小时,视图应如何定位场景。

    10、rubberBandSelectionMode : Qt::ItemSelectionMode

    使用橡皮筋框选择矩形选择图形项的行为。具体值见:QGraphicsScene详解第42个成员函数。

    11、sceneRect : QRectF

    视图可视化的场景区域。如果未设置,或者如果设置了空QRectF,则此属性与QGraphicsScene::sceneRect具有相同的值,并随QGraphicsScene::sceneRect 更改。否则,视图的场景矩形不受场景影响。

     12、transformationAnchor : ViewportAnchor

    视图在转换过程中应如何定位场景。

    13、viewportUpdateMode : ViewportUpdateMode

    三、成员函数

    1、void invalidateScene(const QRectF &rect = QRectF(), QGraphicsScene::SceneLayers layers = QGraphicsScene::AllLayers)

    使场景中的矩形rect内的图层无效并安排重绘。rect内图层的任何缓存内容都将无条件地失效并重新绘制。

    2、[信号] void rubberBandChanged(QRect rubberBandRect, QPointF fromScenePoint, QPointF toScenePoint) 

    当橡皮筋矩形改变时发出这个信号。橡皮筋矩形为rubberBandRect。参数2和参数3为拖动开始位置和拖动结束位置,都是场景中的点。当橡皮筋选择结束时,此信号将与空值一起发射。

    3、void updateScene(const QList<QRectF> &rects)

    立刻更新场景矩形。

    4、void centerOn(const QPointF &pos)

    滚动视口的内容以确保场景坐标pos在视图中居中。

    5、void centerOn(const QGraphicsItem *item) 

    滚动视口的内容以确保图形项在视图中居中。

    6、void drawBackground(QPainter *painter, const QRectF &rect)

    默认调用场景的drawBackground()。

    7、void drawForeground(QPainter *painter, const QRectF &rect) 

    默认调用场景的drawForeground()。使用viewport->update()刷新内容。

    8、void ensureVisible(const QRectF &rect, int xmargin = 50, int ymargin = 50) 

    滚动视口的内容使场景矩形rect可见,边距由 xmargin 和 ymargin 以像素为单位指定。 如果无法到达指定的矩形,则将内容滚动到最近的有效位置。

    9、void ensureVisible(const QGraphicsItem *item, int xmargin = 50, int ymargin = 50)

    滚动视口的内容使图形项可见。如果无法到达指定的图形项所在位置,则将内容滚动到最近的有效位置。

    10、void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) 

    缩放视图矩阵并滚动滚动条以确保场景矩形rect适合视口。rect必须在场景rect内,否则fitInView()不能保证整个矩形都是可见的。此函数只缩放和滚动滚动条但保持视图的旋转、平移或剪切。视图根据aspectRatioMode 进行缩放。

        gphv->fitInView(QRect(0,0,300,300));

    11、void fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio)

    确保 item 紧密地适合视图,根据 aspectRatioMode 缩放视图。

    12、QGraphicsItem *itemAt(const QPoint &pos) 

    返回位置 pos 处的图形项,pos在视口坐标中。如果此位置有多个图形项,则此函数返回最上面的图形项。

    13、QList<QGraphicsItem *> items()

    返回关联场景中所有图形项的列表,按堆叠顺序降序排列。

    14、QList<QGraphicsItem *> items(const QPoint &pos)

    返回视图中位置 pos 处所有图形项的列表。按堆叠顺序降序排列。pos在视口坐标中。

     15、QList<QGraphicsItem *> items(const QRect &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape)

    包含在 rect 中或与 rect 相交的所有项目的列表。 rect 在视口坐标中。模式见:QGraphicsScene详解第42个成员函数。项目按堆叠降序排序。

    16、QList<QGraphicsItem *> items(const QPolygon &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape)

    重载函数。

    17、QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape)

    重载函数。

     18、QPoint mapFromScene(const QPointF &point) 

            QPolygon mapFromScene(const QRectF &rect) 

            QPolygon mapFromScene(const QPolygonF &polygon) 

            QPainterPath mapFromScene(const QPainterPath &path) 

    场景坐标中的点、矩形、多边形、路径转换到视口坐标中的点、多边形、路径。

     19、QPointF mapToScene(const QPoint &point) 

            QPolygonF mapToScene(const QRect &rect) 

            QPolygonF mapToScene(const QPolygon &polygon) 

            QPainterPath mapToScene(const QPainterPath &path) 

    视图坐标转场景坐标。

    20、void render(QPainter *painter, const QRectF &target = QRectF(), const QRect &source = QRect(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio) 

    使用painter将处于视图坐标中的 source 从场景渲染到处于绘制设备坐标中的 target 。如果 source 是一个空矩形,这个函数将使用viewport()->rect() 来确定要绘制的内容。 如果目标是空矩形,则将使用画家绘制设备的完整尺寸(例如,对于 QPrinter,页面大小)。源矩形内容将根据 aspectRatioMode 进行转换以适应目标矩形。 默认情况下,保持长宽比,并缩放源以适应目标。

    此函数可用于将视图的内容捕获到绘图设备上,例如 QImage(例如,截取屏幕截图)或打印到 QPrinter。 例如:

     QGraphicsScene scene;
     scene.addItem(...
     ...
    
     QGraphicsView view(&scene);
     view.show();
     ...
    
     QPrinter printer(QPrinter::HighResolution);
     printer.setPageSize(QPrinter::A4);
     QPainter painter(&printer);
    
     view.render(&painter);
    
     QRect viewport = view.viewport()->rect();
     view.render(&painter,
                 QRectF(0, printer.height() / 2,
                        printer.width(), printer.height() / 2),
                 viewport.adjusted(0, 0, 0, -viewport.height() / 2));

    21、void resetCachedContent()

    重置所有缓存的内容。调用此函数将清除视图的缓存。如果当前缓存模式为 QGraphicsView::CacheNone,则此函数不执行任何操作。当 backgroundBrushQGraphicsScene::backgroundBrush 属性更改时,会自动为您调用此函数。如果重新实现QGraphicsScene::drawBackground() 或 QGraphicsView::drawBackground() 来绘制自定义背景,并且需要触发完全重绘,则只需调用此函数。

    22、void resetTransform()

    将视图转换重置为单位矩阵。

    23、void rotate(qreal angle)

     顺时针旋转当前视图。

    24、QRect rubberBandRect()

    如果当前正在使用橡皮筋进行项目选择,则此函数返回当前橡皮筋区域(在视口坐标中)。当用户不使用橡皮筋时,此函数返回(空值)QRectF()。此 QRect 的一部分可以超出视觉视口,它可以包含负值。

    25、void scale(qreal sx, qreal sy)

     按 (sx, sy) 缩放当前视图。

    26、void setTransform(const QTransform &matrix, bool combine = false)

    设置视图的转换矩阵。参数2见QPainter详解的第46个函数。

    27、void shear(qreal sh, qreal sv)

    通过 (sh, sv) 剪切当前视图转换。剪切效果见QTransform的第22个函数。

    28、void translate(qreal dx, qreal dy)

    将当前视图转换转换为 (dx, dy)。

     

    展开全文
  • 借用QT中的QGraphicsView类实现窗口滑动
  • QGraphicsView简单使用

    千次阅读 2020-10-11 21:32:05
    自定义Item,点 // cgraphicsitem.h #ifndef CGRAPHICSITEM_H #define CGRAPHICSITEM_H #include <QGraphicsItem> #include <QGraphicsSceneMouseEvent&... CGraphicsItem(QPointF p,QGraphicsItem* parent =

    自定义Item,点

    // cgraphicsitem.h
    #ifndef CGRAPHICSITEM_H
    #define CGRAPHICSITEM_H
    
    #include <QGraphicsItem>
    #include <QGraphicsSceneMouseEvent>
    class CGraphicsItem : public QGraphicsItem
    {
    public:
        CGraphicsItem(QPointF p,QGraphicsItem* parent = 0);
        QPointF getPoint(){return m_point;}
        void setPoint(QPointF p){m_point = p;}
    protected:
        virtual QRectF boundingRect() const override;
        virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
        virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *e);
    private:
        QPointF m_point;
    };
    
    #endif // CGRAPHICSITEM_H
    
    // cgraphicsitem.cpp
    
    #include "cgraphicsitem.h"
    #include <QPen>
    #include <QBrush>
    #include <QPainter>
    #include <QGraphicsScene>
    #include <QCursor>
    CGraphicsItem::CGraphicsItem(QPointF p,QGraphicsItem* parent)
        : m_point(p)
        , QGraphicsItem(parent)
    {
        setFlags(QGraphicsItem::ItemIsFocusable|
                 QGraphicsItem::ItemIsSelectable|
                 QGraphicsItem::ItemIsMovable);
        this->setCursor(Qt::PointingHandCursor);
    }
    
    QRectF CGraphicsItem::boundingRect() const
    {
        return QRectF(-4,-4,8,8);
    }
    
    void CGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        Q_UNUSED(option);
        Q_UNUSED(widget);
        QPen pen(Qt::yellow,2);
        QBrush brush(Qt::blue);
        this->setPos(m_point);
        painter->setPen(pen);
        painter->setBrush(brush);
        painter->drawEllipse(-4,-4,8,8);
    }
    
    void CGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
    {
        if(e->buttons() == Qt::LeftButton) {
        qreal x = e->scenePos().x() - e->lastScenePos().x();
        qreal y = e->scenePos().y() - e->lastScenePos().y();
        this->parentItem()->moveBy(x,y);
        }
        return QGraphicsItem::mouseMoveEvent(e);
    }
    

    scene类负责响应view信号,实时画图

    // cgraphicsscene.h
    #ifndef CGRAPHICSSCENE_H
    #define CGRAPHICSSCENE_H
    
    #include <QGraphicsScene>
    #include "cgraphicsitem.h"
    #include <QPainterPath>
    #include <QGraphicsPathItem>
    class CGraphicsScene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        enum Type {
            T_None,
            T_Point,
            T_Line,
            T_Circle,
            T_Ellipse,
            T_Rect,
            T_RoundRect,
            T_Polygon,
            T_Bezier
        };
        enum State {
            S_None,
            S_Begin,
            S_Moving,
            S_Press,
            S_End
        };
    
        CGraphicsScene(QObject *parent = 0);
    private:
        void BeginDraw(QPointF beginPos,QPointF nextPos,int type);
        void MovingDraw(QPointF beginPos,QPointF movingPos,int type);
        void PressDraw(QPointF beginPos,QPointF pressPos,int type);
        void EndDraw(QPointF beginPos,QPointF endgPos,int type);
    public slots:
        void OnDrawImage(QPointF beginPos,QPointF nextPos,int type,int state);
    private:
        QList<QGraphicsPathItem*> m_itemList;
        QGraphicsPathItem *m_currentItem;
        QVector<QPointF> m_polygonVec;
        QVector<QPointF> m_bezierVec;
    };
    
    #endif // CGRAPHICSSCENE_H
    
    // cgraphicsscene.cpp
    #include "cgraphicsscene.h"
    #include <cmath>
    #include <QPolygonF>
    #include <QDebug>
    CGraphicsScene::CGraphicsScene(QObject *parent)
        : QGraphicsScene(parent)
        , m_currentItem(NULL)
    {
    
    }
    
    void CGraphicsScene::BeginDraw(QPointF beginPos, QPointF nextPos, int type)
    {
        Q_UNUSED(nextPos);
        m_currentItem = new QGraphicsPathItem;
        m_currentItem->setFlags(QGraphicsItem::ItemIsSelectable|
                                QGraphicsItem::ItemIsFocusable);
        m_currentItem->setPen(QPen(Qt::blue,5));
        switch(type)
        {
        case T_Point:
        {
             CGraphicsItem *item = new CGraphicsItem(beginPos,m_currentItem);
             Q_UNUSED(item);
        }
            break;
        case T_Line:
        case T_Circle:
        case T_Ellipse:
        case T_Rect:
        case T_RoundRect:
        {
            QPainterPath path;
            path.moveTo(beginPos);
            path.lineTo(beginPos);
            m_currentItem->setPath(path);
        }
            break;
        case T_Polygon:
            m_polygonVec.push_back(beginPos);
            break;
        case T_Bezier:
            m_bezierVec.push_back(beginPos);
            break;
        default:break;
        }
        addItem(m_currentItem);
    }
    
    void CGraphicsScene::MovingDraw(QPointF beginPos, QPointF movingPos, int type)
    {
        qreal w = movingPos.x() - beginPos.x();
        qreal h = movingPos.y() - beginPos.y();
        switch(type)
        {
        case T_Line:
        {
            QPainterPath path;
            path.moveTo(beginPos);
            path.lineTo(movingPos);
            m_currentItem->setPath(path);
        }
            break;
        case T_Circle:
        {
            QPainterPath path;
            fabs(w) > fabs(h)? path.addEllipse(beginPos.x(),beginPos.y(),h,h)\
                             : path.addEllipse(beginPos.x(),beginPos.y(),w,w);
            m_currentItem->setPath(path);
        }
            break;
        case T_Ellipse:
        {
            QPainterPath path;
            path.addEllipse(beginPos.x(),beginPos.y(),w,h);
            m_currentItem->setPath(path);
        }
            break;
        case T_Rect:
        {
            QPainterPath path;
            path.addRect(beginPos.x(),beginPos.y(),w,h);
            m_currentItem->setPath(path);
        }
            break;
        case T_RoundRect:
        {
            QPainterPath path;
            path.addRoundRect(beginPos.x(),beginPos.y(),w,h,25);
            m_currentItem->setPath(path);
        }
            break;
        case T_Polygon:
        {
            QVector<QPointF> tmpVec = m_polygonVec;
            tmpVec.push_back(movingPos);
            QPainterPath path;
            QPolygonF tmpPolygon(tmpVec);
            path.addPolygon(tmpPolygon);
            m_currentItem->setPath(path);
        }
            break;
        case T_Bezier:
        {
            QVector<QPointF> tmpVec = m_bezierVec;
            tmpVec.push_back(movingPos);
            QPainterPath path;
            QPolygonF tmpPolygon(tmpVec);
            path.addPolygon(tmpPolygon);
            m_currentItem->setPath(path);
        }
            break;
        default:break;
        }
    }
    
    void CGraphicsScene::PressDraw(QPointF beginPos, QPointF pressPos, int type)
    {
        Q_UNUSED(beginPos);
        switch(type)
        {
        case T_Point:
        {
             CGraphicsItem *item = new CGraphicsItem(pressPos,m_currentItem);
             Q_UNUSED(item);
        }
            break;
        case T_Polygon:
        {
            m_polygonVec.push_back(pressPos);
            QPainterPath path;
            QPolygonF tmpPolygon(m_polygonVec);
            path.addPolygon(tmpPolygon);
            m_currentItem->setPath(path);
        }
            break;
        case T_Bezier:
        {
            m_bezierVec.push_back(pressPos);
            QPainterPath path;
            QPolygonF tmpPolygon(m_bezierVec);
            path.addPolygon(tmpPolygon);
            m_currentItem->setPath(path);
        }
            break;
        default:break;
        }
    
    }
    
    void CGraphicsScene::EndDraw(QPointF beginPos, QPointF endPos, int type)
    {
        qreal w = endPos.x() - beginPos.x();
        qreal h = endPos.y() - beginPos.y();
        switch(type)
        {
        case T_Point:
        {
            //CGraphicsItem *item = new CGraphicsItem(beginPos,m_currentItem);
            //Q_UNUSED(item);
        }
            break;
        case T_Line:
        {
            QPainterPath path;
            path.moveTo(beginPos);
            path.lineTo(endPos);
            m_currentItem->setPath(path);
        }
            break;
        case T_Circle:
        {
            QPainterPath path;
            fabs(w) > fabs(h)? path.addEllipse(beginPos.x(),beginPos.y(),h,h)\
                             : path.addEllipse(beginPos.x(),beginPos.y(),w,w);
            m_currentItem->setPath(path);
        }
            break;
        case T_Ellipse:
        {
            QPainterPath path;
            path.addEllipse(beginPos.x(),beginPos.y(),w,h);
            m_currentItem->setPath(path);
        }
            break;
        case T_Rect:
        {
            QPainterPath path;
            path.addRect(beginPos.x(),beginPos.y(),w,h);
            m_currentItem->setPath(path);
        }
            break;
        case T_RoundRect:
        {
            QPainterPath path;
            path.addRoundRect(beginPos.x(),beginPos.y(),w,h,25);
            m_currentItem->setPath(path);
        }
            break;
        case T_Polygon:
        {
            m_polygonVec.push_back(endPos);
            QPainterPath path;
            QPolygonF tmpPolygon(m_polygonVec);
            path.addPolygon(tmpPolygon);
            path.closeSubpath();
            m_currentItem->setPath(path);
            m_polygonVec.clear();
        }
            break;
        case T_Bezier:
        {
            m_bezierVec.push_back(endPos);
            QPainterPath path(m_bezierVec[0]);
            for(int i=0; i<m_bezierVec.size()-1; i++)
            {
                QPointF sp = m_bezierVec[i];
                QPointF ep = m_bezierVec[i+1];
                QPointF c1 = QPointF((sp.x()+ep.x())/2,sp.y());
                QPointF c2 = QPointF((sp.x()+ep.x())/2,ep.y());
                path.cubicTo(c1,c2,ep);
            }
            m_currentItem->setPath(path);
            m_bezierVec.clear();
        }
            break;
        default:break;
        }
        m_currentItem->setSelected(false);
        m_itemList.push_back(m_currentItem);
    }
    
    void CGraphicsScene::OnDrawImage(QPointF beginPos, QPointF nextPos, int type, int state)
    {
        if (state == S_Begin) {
            BeginDraw(beginPos,nextPos,type);
        }
        else if (state == S_Moving) {
            MovingDraw(beginPos,nextPos,type);
        }
        else if (state == S_Press) {
            PressDraw(beginPos,nextPos,type);
        }
        else if (state == S_End) {
            EndDraw(beginPos,nextPos,type);
        }
    }
    

    view类,负责响应鼠标事件,向scene传递信号

    // cgraphicsview.h
    #ifndef CGRAPHICSVIEW_H
    #define CGRAPHICSVIEW_H
    #include <QObject>
    #include <QGraphicsView>
    #include <QMouseEvent>
    class CGraphicsView : public QGraphicsView
    {
        Q_OBJECT
    public:
        enum Type {
            T_None,
            T_Point,
            T_Line,
            T_Circle,
            T_Ellipse,
            T_Rect,
            T_RoundRect,
            T_Polygon,
            T_Bezier
        };
        enum State {
            S_None,
            S_Begin,
            S_Moving,
            S_Press,
            S_End
        };
    
        CGraphicsView(QWidget* parent = 0);
        void setState(State state){m_state = state;}
        void setType(Type type){m_type = type;}
    protected:
        void mousePressEvent(QMouseEvent *e);
        void mouseReleaseEvent(QMouseEvent *e);
        void mouseMoveEvent(QMouseEvent *e);
    signals:
        void drawImage(QPointF beginPos,QPointF nextPos,int type,int state);
    private:
        Type m_type;
        State m_state;
        QPointF m_beginPos;
        QPointF m_movingPos;
        QPointF m_endPos;
    };
    
    #endif // CGRAPHICSVIEW_H
    
    // cgraphicsview.cpp
    #include "cgraphicsview.h"
    #include <QPainter>
    CGraphicsView::CGraphicsView(QWidget *parent)
        : QGraphicsView(parent)
        , m_state(S_None)
        , m_type(T_None)
    {
        setRenderHints(QPainter::Antialiasing);
        setBackgroundBrush(Qt::gray);
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setMouseTracking(true);
    }
    
    void CGraphicsView::mousePressEvent(QMouseEvent *e)
    {
        if(e->button() == Qt::LeftButton) {
            if(m_state == S_Begin) {
                m_beginPos = e->pos();
                emit drawImage(m_beginPos,m_beginPos,m_type,m_state);
                m_state = S_Moving;
            }
            else if(m_state == S_Moving) {
                m_endPos = e->pos();
                switch(m_type)
                {
                case T_Point:
                case T_Polygon:
                case T_Bezier:
                    emit drawImage(m_beginPos,m_endPos,m_type,S_Press);
                    break;
                case T_Line:
                case T_Circle:
                case T_Ellipse:
                case T_Rect:
                case T_RoundRect:
                    m_state = S_End;
                    emit drawImage(m_beginPos,m_endPos,m_type,m_state);
                    break;
                default:break;
                }
            }
        }
        else if(e->button() == Qt::RightButton) {
            if (m_state == S_Moving) {
                m_endPos = e->pos();
                if(m_type == T_Point || m_type == T_Polygon || m_type == T_Bezier) {
                    m_state = S_End;
                    emit drawImage(m_endPos,m_endPos,m_type,m_state);
                }
            }
        }
        return QGraphicsView::mousePressEvent(e);
    }
    
    void CGraphicsView::mouseReleaseEvent(QMouseEvent *e)
    {
        return QGraphicsView::mouseReleaseEvent(e);
    }
    
    void CGraphicsView::mouseMoveEvent(QMouseEvent *e)
    {
        if(m_state == S_Moving)
        {
            m_movingPos = e->pos();
            emit drawImage(m_beginPos,m_movingPos,m_type,m_state);
        }
        return QGraphicsView::mouseMoveEvent(e);
    }
    
    

    使用

    // widget.h
    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QResizeEvent>
    #include "cgraphicsscene.h"
    #include "cgraphicsview.h"
    
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
    protected:
        void resizeEvent(QResizeEvent *e);
    private slots:
        void on_pointBtn_clicked();
        void on_lineBtn_clicked();
        void on_circleBtn_clicked();
        void on_ellipseBtn_clicked();
        void on_rectBtn_clicked();
        void on_roundRectBtn_clicked();
        void on_polygonBtn_clicked();
        void on_bezierBtn_clicked();
        void on_clearBtn_clicked();
    private:
        Ui::Widget *ui;
        CGraphicsScene *m_scene;
        CGraphicsView *m_view;
    };
    
    #endif // WIDGET_H
    
    // widget.cpp
    #include "widget.h"
    #include "ui_widget.h"
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        m_view = new CGraphicsView(ui->widget_2);
        m_scene = new CGraphicsScene;
        m_view->setScene(m_scene);
        connect(m_view,&CGraphicsView::drawImage,m_scene,&CGraphicsScene::OnDrawImage);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::resizeEvent(QResizeEvent *e)
    {
        m_view->resize(ui->widget_2->width(),ui->widget_2->height());
        m_scene->setSceneRect(0,0,ui->widget_2->width(),ui->widget_2->height());
        return QWidget::resizeEvent(e);
    }
    
    void Widget::on_pointBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Point);
    }
    
    void Widget::on_lineBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Line);
    }
    
    void Widget::on_circleBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Circle);
    }
    
    void Widget::on_ellipseBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Ellipse);
    }
    
    void Widget::on_rectBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Rect);
    }
    
    void Widget::on_roundRectBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_RoundRect);
    }
    
    void Widget::on_polygonBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Polygon);
    }
    
    void Widget::on_bezierBtn_clicked()
    {
        m_view->setState(CGraphicsView::S_Begin);
        m_view->setType(CGraphicsView::T_Bezier);
    }
    
    void Widget::on_clearBtn_clicked()
    {
        m_scene->clear();
    }
    
    

    效果图

    展开全文
  • I have a custom class derived from QGraphicsView that implements a slot call scrollHorizontal(int dx), inside the code is simplyvoid CustomView::scrollHorizontal(int dx){scrollContentsBy(dx, 0);...
  • QGraphicsView使用详解

    万次阅读 多人点赞 2019-04-15 17:59:03
    一、GraphicsView框架简介 QT4.2开始引入了Graphics View框架用来取代QT3中的Canvas模块,并作出了改进,Graphics ...GraphicsView框架结构主要包含三个主要的类QGraphicsScene(场景)、QGraphicsView(视图)、...
  • 我有自定义QGraphicsView和QGraphicsScene。在QGraphicsScene内部我覆盖了void drawBackground(QPainter *painter, const QRectF &rect)并基于布尔标志我想要打开和关闭网格。我尝试在我的函数中调用clear()或...
  • QGraphicsView框架容易忽视的坐标问题-“画布”QgraphicsScene到底放在了哪儿?
  • QGraphicsView-理论基础

    2021-04-25 19:14:39
    QGraphicsView 以下简称:view 功能描述:提供一个小部件,用于显示QGraphicsScene的内容。要创建带有几何(形状:圆形、方形、二维三维等)场景,需要参考QGraphicsScene。view也是 Graphics View Framework的一...
  • QGraphicsItem、QGraphicsView、QGraphicsScene 文章目录QGraphicsItem、QGraphicsView、QGraphicsScene前言一、自定义QGraphicsItem二、自定义QGraphicsView样例总结 前言 使用QGraphicsItem、QGraphicsScene、...
  • QGraphicsView 框架学习(一)、图形元素的编辑 代码在 http://download.csdn.net/detail/firebolt2002/8782273 一、给图形对象加控制点,用户通过鼠标来操作控制点来编辑图形,参考MFC drawcli的实现。 很多人通过...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,054
精华内容 1,621
关键字:

qgraphicsview

友情链接: android_cdc_driver.zip