使用QT繪製一個多邊形

1. 概述

能夠經過QT的重繪事件和鼠標事件來繪製多邊形,最簡單的辦法就是在繼承QWidget的窗體中重寫paintEvent、mousePressEvent等事件處理函數。QT提供了圖形繪製接口QPainter,經過該接口能夠繪製多種圖形,包括多邊形。this

2. 實現

2.1. 代碼

新建一個基於QWidget的QT界面類GraphicsPainter,將其放置到想要顯示的窗體中。該類的具體代碼:spa

GraphicsPainter.h:.net

#ifndef GRAPHICSPAINTER_H
#define GRAPHICSPAINTER_H

#include <QWidget>

class GraphicsPainter : public QWidget
{
    Q_OBJECT
public:
    explicit GraphicsPainter(QWidget *parent = nullptr);

    void SetDraw(bool bDraw);

signals:
    void singalDrawOver();

public slots:

protected:
    void paintEvent(QPaintEvent *);     //繪製
    void mousePressEvent(QMouseEvent *e);       //按下
    void mouseMoveEvent(QMouseEvent *e);        //移動
    void mouseReleaseEvent(QMouseEvent *e);     //鬆開
    void mouseDoubleClickEvent(QMouseEvent *event);        //雙擊


    bool bDraw;             //是否處於繪製狀態
    bool bLeftClick;            //是否已經開始左鍵點擊,同時標識是否開始進行繪製
    bool bMove;             //是否處於繪製時的鼠標移動狀態

    QVector<QPointF> pointList;
    QPointF movePoint;
};

#endif // GRAPHICSPAINTER_H

GraphicsPainter.cpp:code

#include "graphicspainter.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>

GraphicsPainter::GraphicsPainter(QWidget *parent) : QWidget(parent)
{
    //填充背景色
    setAutoFillBackground(true);
    setBackgroundRole(QPalette::Base);

    bDraw = false;
    bLeftClick = false;
    bMove = false;
    setMouseTracking(true);
}

void GraphicsPainter::SetDraw(bool bDraw)
{
    this->bDraw = bDraw;
    pointList.clear();
}

//從新實現paintEvent
void GraphicsPainter::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    if(bDraw)
    {
       painter.setPen(QColor(255,0,0));
       QVector<QLineF> lines;
       for(int i = 0; i<pointList.size()-1; i++)
       {
           QLineF line(QPointF(pointList[i].x(), pointList[i].y()), QPointF(pointList[i+1].x(), pointList[i+1].y()));
           lines.push_back(line);
       }
       if(bMove&&pointList.size()>0)
       {
           QLineF line(QPointF(pointList[pointList.size()-1].x(), pointList[pointList.size()-1].y()), movePoint);
           lines.push_back(line);
       }
       painter.drawLines(lines);
    }
}

//按下
void GraphicsPainter::mousePressEvent(QMouseEvent *e)
{
    if(bDraw)
    {
        if(!bLeftClick)
        {
            pointList.clear();
            bLeftClick = true;
        }
    }
    //qDebug()<<"Press";
}

//移動
void GraphicsPainter::mouseMoveEvent(QMouseEvent *e)
{
    if(bDraw&&bLeftClick)
    {
        movePoint = e->pos();
        bMove = true;
        this->update();
    }
    //qDebug()<<"Move";
}

//鬆開
void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e)
{
    if(bDraw&&bLeftClick)
    {
        pointList.push_back(QPointF(e->x(), e->y()));
        bMove = false;
        this->update();
    }
    //qDebug()<<"Release";
}

//雙擊
void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(bDraw)
    {
        bLeftClick = false;
        pointList.push_back(pointList[0]);
        this->update();
        singalDrawOver();
    }
    //qDebug()<<"DoubleClick";
}

2.2. 解析

在從新實現的重繪事件中,經過QPainter繪製了一系列線組成線串,最後會首尾相連造成多邊形。這裏的bMove標識是否處於繪製時的鼠標移動狀態,只有鼠標左鍵點擊後纔會肯定爲真正的節點:blog

//從新實現paintEvent
void GraphicsPainter::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    if(bDraw)
    {
       painter.setPen(QColor(255,0,0));
       QVector<QLineF> lines;
       for(int i = 0; i<pointList.size()-1; i++)
       {
           QLineF line(QPointF(pointList[i].x(), pointList[i].y()), QPointF(pointList[i+1].x(), pointList[i+1].y()));
           lines.push_back(line);
       }
       if(bMove&&pointList.size()>0)
       {
           QLineF line(QPointF(pointList[pointList.size()-1].x(), pointList[pointList.size()-1].y()), movePoint);
           lines.push_back(line);
       }
       painter.drawLines(lines);
    }
}

鼠標按下事件中,主要是經過bLeftClick值來肯定是否已經處於左鍵點擊狀態,同時還能標識是否開始進行繪製。一旦開始,就會把上次繪製的節點清除。繼承

//按下
void GraphicsPainter::mousePressEvent(QMouseEvent *e)
{
    if(bDraw)
    {
        if(!bLeftClick)
        {
            pointList.clear();
            bLeftClick = true;
        }
    }
    //qDebug()<<"Press";
}

一旦鼠標鬆開,就能夠肯定一個節點,此時須要調用update()進行重繪:接口

//鬆開
void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e)
{
    if(bDraw&&bLeftClick)
    {
        pointList.push_back(QPointF(e->x(), e->y()));
        bMove = false;
        this->update();
    }
    //qDebug()<<"Release";
}

當開始進行繪製後,移動鼠標就會處於繪製時的鼠標移動狀態,這時就會肯定bMove爲true,重繪事件就會將該鼠標點繪製出來,從而達到待選節點的效果:事件

//移動
void GraphicsPainter::mouseMoveEvent(QMouseEvent *e)
{
    if(bDraw&&bLeftClick)
    {
        movePoint = e->pos();
        bMove = true;
        this->update();
    }
    //qDebug()<<"Move";
}

鼠標雙擊後,將第一個點加入到當前多邊形的節點中後,達到首尾相連的效果,此時就會結束繪製:ci

//雙擊
void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(bDraw)
    {
        bLeftClick = false;
        pointList.push_back(pointList[0]);
        this->update();
        singalDrawOver();
    }
    //qDebug()<<"DoubleClick";
}

這裏必定要注意,當進行雙擊操做時,首先會觸發一次mousePressEvent,而後觸發一次mouseReleaseEvent,接着纔會觸發一次mouseDoubleClickEvent,最後還會觸發一次mouseReleaseEvent。因此這就是這裏設置bLeftClick這個參數緣由:當觸發mouseDoubleClickEvent後,bLeftClick設置爲false,第二次觸發mouseReleaseEvent時內部就不會在作任何操做了。

3. 結果

最終運行的結果以下所示:

QT繪製多邊形

代碼地址

相關文章
相關標籤/搜索