Qt学习_QGraphics进阶学习笔记

Posted Leslie X徐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt学习_QGraphics进阶学习笔记相关的知识,希望对你有一定的参考价值。

QGraphics进阶学习

1.保存图片函数

QPixmap QWidget::grab(const QRect &rectangle = QRect(QPoint(0, 0), QSize(-1, -1)))

Renders the widget into a pixmap restricted by the given rectangle. If the widget has any children, then they are also painted in the appropriate positions.
If a rectangle with an invalid size is specified (the default), the entire widget is painted.

2.场景里面添加QWidget部件

 QGraphicsProxyWidget* item = _scene->addWidget(new QLineEdit("hello"));
    item->resize(50,50);
    item->setPos(_scene->sceneRect().center());
    item->setFlags(QGraphicsItem::ItemIsMovable|
                   QGraphicsItem::ItemIsSelectable|
                   QGraphicsItem::ItemIsFocusable);

3.对QWidget部件的移动,对scene重写

#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H

#include <QGraphicsScene>

/** 可以移动QGraphicsProxyWidget的scene
 * @brief The GraphicsScene class
 */
class GraphicsScene : public QGraphicsScene

    Q_OBJECT
public:
    explicit GraphicsScene(QObject *parent = nullptr);
    void setMoveMode(bool move)m_isMoveMode=move;
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);


private:
    QGraphicsItem   *m_pItemSelectedQ_NULLPTR;                   // 鼠标单选item
    QPoint          m_shiftOrg;                         // 鼠标点选item中位置相对于item原点的偏移量
    bool            m_isMoveModefalse;
;

#endif // GRAPHICSSCENE_H

#include "GraphicsScene.h"
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsItem>
#include <QGraphicsProxyWidget>
#include <QMenu>

GraphicsScene::GraphicsScene(QObject *parent) : QGraphicsScene(parent)



// 鼠标按下获取当前单选中的QGraphicsProxyWidget图元对象
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)


//    qDebug() << "scene mouse press";
    QGraphicsScene::mousePressEvent(event);
    //左键则弹出menu框
    if (event->button() == Qt::RightButton)
        m_pItemSelected = nullptr;
        if(items(event->scenePos()).isEmpty())
        
            QMenu *menu = new QMenu();
            menu->setAttribute(Qt::WA_DeleteOnClose);
            menu->addAction("editMode",this,[this]()
                setMoveMode(false);
            );
            menu->addAction("moveMode",this,[this]()
                setMoveMode(true);
            );
            menu->popup(event->screenPos());
        

    

    //进入edit模式则直接退出
    if(m_isMoveMode==false)
        m_pItemSelected = nullptr;
        return;
    

    //进入move模式则不可编辑
    if (event->button() == Qt::LeftButton)
    
        // 检测光标下是否有 item
        m_pItemSelected = nullptr;
        foreach (QGraphicsItem *item, items(event->scenePos()))
        
            if (item->type() == QGraphicsProxyWidget::Type)   // 代理Widget
            
                QGraphicsProxyWidget *proxyWidget = qgraphicsitem_cast<QGraphicsProxyWidget *>(item);
                QPointF point = proxyWidget->mapToScene(QPointF(0.0, 0.0));
                m_shiftOrg.setX(event->scenePos().x() - point.x());
                m_shiftOrg.setY(event->scenePos().y() - point.y());
                m_pItemSelected = item;
                break;
            
        
    



// 鼠标移动过程中跟随位置改变
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)

//    qDebug() << "scene mouse move";
    QGraphicsScene::mouseMoveEvent(event);
    if(m_pItemSelected != nullptr)
    
        m_pItemSelected->setPos(event->scenePos().x() - m_shiftOrg.x(), event->scenePos().y() - m_shiftOrg.y());
    

// 鼠标释放后作为最后的位置
void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)

//    qDebug() << "scene mouse release";
    QGraphicsScene::mouseReleaseEvent(event);

    if(m_pItemSelected != nullptr)
    
        m_pItemSelected->setPos(event->scenePos().x() - m_shiftOrg.x(), event->scenePos().y() - m_shiftOrg.y());
        m_pItemSelected = nullptr;
    


4.自定义QGraphicsLineItem 创建动态连线

需要重写 QRectF boundingRect()void paint() 函数

需要添加头尾两个item指针

头文件

#ifndef CONNECTLINE_H
#define CONNECTLINE_H

#include <QGraphicsLineItem>

class ConnectLine : public QGraphicsLineItem

public:
    ConnectLine();
    ConnectLine(QGraphicsItem* startitem, QGraphicsItem* enditem);
    ~ConnectLine();
    double getlength()return _length;
private:
    QGraphicsItem* _startItem;
    QGraphicsItem* _endItem;
    double _length=0;

    // QGraphicsItem interface
public:
    virtual QRectF boundingRect() const;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
;

#endif // CONNECTLINE_H

源文件

#include "ConnectLine.h"
#include <QPainter>
#include <QDebug>

ConnectLine::ConnectLine()




ConnectLine::ConnectLine(QGraphicsItem *startitem, QGraphicsItem *enditem)

    _startItem = startitem;
    _endItem = enditem;
    this->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);


ConnectLine::~ConnectLine()



QRectF ConnectLine::boundingRect() const

    return QRectF(_startItem->pos()-QPointF(10,10),_endItem->pos()+QPointF(10,10));


void ConnectLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)

//    painter->drawLine(_startItem->pos(),_endItem->pos());

    QPainterPath path;
    path.moveTo(_startItem->pos());
    path.cubicTo(_startItem->pos()+QPointF(50,0),_endItem->pos()-QPointF(50,0),_endItem->pos());
    _length = path.length();
    painter->drawPath(path);



5.自定义 textitem 双击可以编辑

知识点:

flags Qt::TextInteractionFlags

QGraphicsTextItem::setTextInteractionFlags(Qt::TextInteractionFlag::TextEditorInteraction);

头文件

#ifndef GRAPHICSEDITABLETEXTITEM_H
#define GRAPHICSEDITABLETEXTITEM_H

#include <QGraphicsTextItem>

class GraphicsEditableTextItem : public QGraphicsTextItem

    Q_OBJECT

public:
    GraphicsEditableTextItem();
    GraphicsEditableTextItem(const QString& str);

    // QGraphicsItem interface
protected:
    void focusOutEvent(QFocusEvent *event) override;
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
;

#endif // GRAPHICSEDITABLETEXTITEM_H

源文件

#include "GraphicsEditableTextItem.h"

GraphicsEditableTextItem::GraphicsEditableTextItem()

    this->setFlags(QGraphicsItem::ItemIsMovable |
                   QGraphicsItem::ItemIsFocusable|
                   QGraphicsItem::ItemIsSelectable);


GraphicsEditableTextItem::GraphicsEditableTextItem(const QString &str)

    this->setPlainText(str);
    this->setFlags(QGraphicsItem::ItemIsMovable |
                   QGraphicsItem::ItemIsFocusable|
                   QGraphicsItem::ItemIsSelectable);


void GraphicsEditableTextItem::focusOutEvent(QFocusEvent *event)

    this->setSelected(false);
    if(this->textInteractionFlags()==Qt::TextInteractionFlag::TextEditorInteraction)
        this->setTextInteractionFlags(Qt::TextInteractionFlag::NoTextInteraction);
    
    QGraphicsTextItem::focusOutEvent(event);


void GraphicsEditableTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)

    if(this->textInteractionFlags()==Qt::TextInteractionFlag::NoTextInteraction)
        this->setTextInteractionFlags(Qt::TextInteractionFlag::TextEditorInteraction);
    
    QGraphicsTextItem::mouseDoubleClickEvent(event);


6.绘制外轮廓

// 绘制轮廓
void ConnectLine::drawOutline(QPainter *painter, QPainterPath path)

    // 生成可填充的轮廓
    QPainterPathStroker stroker;
    stroker.setCapStyle(Qt::RoundCap);  // 端点风格
    stroker.setJoinStyle(Qt::RoundJoin);  // 连接样式
    stroker.setDashPattern(Qt::DashLine);  // 虚线图案
    stroker.setWidth(10);  // 宽度

    // 生成一个新路径(可填充区域),表示原始路径 path 的轮廓
    QPainterPath outlinePath = stroker.createStroke(path);

    // 绘制轮廓时所用的画笔(轮廓外边框灰色部分)
    QPen pen = painter->pen();
    pen.setColor(QColor(0, 160, 230));
    pen.setWidth(10);

    // 用指定的画笔 pen 绘制 outlinePath
    // painter->strokePath(outlinePath, pen);
    painter->setPen(pen);
    painter->drawPath(outlinePath);

    // 用指定的画刷 brush 填充路径 outlinePath
    painter->fillPath(outlinePath, QBrush(Qt::yellow));


7.MyMind思维导图

void MainWindow::on_pushButton_clicked()

    QGraphicsItem* previtem=0;
    qDebug()<<_scene->selectedItems();
    if(!_scene->selectedItems().isEmpty()) 
        previtem = _scene->selectedItems().at(0);
        qDebug()<<"selected previtem";
    

    GraphicsEditableTextItem* textitem = new GraphicsEditableTextItem("hello");
    _scene->addItem(textitem);

    if(previtem)
        qDebug()<<"draw line";
        textitem->setPos(previtem->pos()+QPointF(100,0));
        ConnectLine* line = new ConnectLine(previtem,textitem);
        _scene->addItem(line);
    

8.保存

void MainWindow::on_actsave_triggered()

    QPixmap pic = ui->View->grab(scene->sceneRect().toRect());
    pic.save("D:\\\\lesliex\\\\test.jpg");

9.给QgraphicsTextItem加上背景色

void GraphicsEditableTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)

    painter->setBrush(Qt::yellow);
    painter->drawRect(this->boundingRect());
    QGraphicsTextItem::paint(painter,option,widget);

10.利用boundingrect获取起始点和终点

void ConnectLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)

    QPointF startpos = mapFromItem(_startItem, _startItem->boundingRect().center());
    QPointF endpos =mapFromItem( _endItem,_endItem->boundingRect().center());

    painter->setPen(this->pen());

    QPainterPath path;
    path.moveTo(startpos);

    if(startpos.x()>endpos.x())
        path.cubicTo(startpos-QPointF(100,0),endpos+QPointF(100,0),endpos);
    else
        path.cubicTo(startpos+QPointF(100,0),endpos-QPointF(100,0),endpos);

    painter->drawPath(path);


11.向下移动

if(previtem)
        qDebug()<<"draw line";
        textitem->setPos(previtem->pos()+QPointF(100,0));
        while(!textitem->collidingItems().isEmpty())
            textitem->setPos(textitem->collidingItems()以上是关于Qt学习_QGraphics进阶学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL进阶学习笔记四:MySQL存储过程之定义条件,处理过程及存储过程的管理!(视频序号:进阶_11,12)

学习笔记python 进阶特性

MYSQL进阶学习笔记五:MySQL函数的创建!(视频序号:进阶_13)

MYSQL进阶学习笔记三:MySQL流程控制语句!(视频序号:进阶_7-10)

PyTorch学习笔记:PyTorch进阶训练技巧

MYSQL进阶学习笔记十六:MySQL 监控!(视频序号:进阶_35)