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.保存为Json格式并读取

保存:

void MainWindow::on_actsave_triggered()

    //保存为图片
    QPixmap pic = ui->View->grab(scene->sceneRect().toRect());
    pic.save("D:\\\\lesliex\\\\test.jpg");
    qDebug()<<scene->items(scene->itemsBoundingRect());

    //保存图元的数据
    QJsonArray array;
    for(auto item:scene->items(scene->itemsBoundingRect()))
        QJsonObject obj;
        obj.insert("x",item->pos().x());
        obj.insert("y",item->pos().y());
        obj.insert("type",item->type());
        obj.insert("zValue",item->zValue());
        array.append(obj);
    
    QJsonDocument Doc(array);
    QFile file("D:\\\\lesliex\\\\test.txt");
    file.open(QIODevice::ReadWrite);
    file.write(Doc.toJson());
    file.close();

Json数据

[
    
        "type": 4,//图元类型
        "x": 325,//x坐标
        "y": 277,//y坐标
        "zValue": 0//z坐标
    ,
    
        "type": 4,
        "x": 297,
        "y": 277,
        "zValue": 0
    
]

读取:

void MainWindow::on_actload_triggered()

    //读取图元的数据
    QFile file("D:\\\\lesliex\\\\test.txt");
    file.open(QIODevice::ReadWrite);
    QByteArray data = file.readAll();
    file.close();

    QJsonDocument Doc(QJsonDocument::fromJson(data));
    QJsonArray array(Doc.array());
    for(auto i:array)
        QJsonObject obj = i.

以上是关于Qt学习_QGraphics进阶学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记python 进阶特性

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

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

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

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

MYSQL进阶学习笔记九:MySQL事务的应用!(视频序号:进阶_21-22)