Qt實(shí)現(xiàn)繪制一個(gè)簡單多邊形的示例代碼
1. 概述
可以通過QT的重繪事件和鼠標(biāo)事件來繪制多邊形,最簡單的辦法就是在繼承QWidget的窗體中重寫paintEvent、mousePressEvent等事件處理函數(shù)。QT提供了圖形繪制接口QPainter,通過該接口可以繪制多種圖形,包括多邊形。
2. 實(shí)現(xiàn)
2.1 代碼
新建一個(gè)基于QWidget的QT界面類GraphicsPainter,將其放置到想要顯示的窗體中。該類的具體代碼:
GraphicsPainter.h:
#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); //移動(dòng)
void mouseReleaseEvent(QMouseEvent *e); //松開
void mouseDoubleClickEvent(QMouseEvent *event); //雙擊
bool bDraw; //是否處于繪制狀態(tài)
bool bLeftClick; //是否已經(jīng)開始左鍵點(diǎn)擊,同時(shí)標(biāo)識是否開始進(jìn)行繪制
bool bMove; //是否處于繪制時(shí)的鼠標(biāo)移動(dòng)狀態(tài)
QVector<QPointF> pointList;
QPointF movePoint;
};
#endif // GRAPHICSPAINTER_HGraphicsPainter.cpp:
#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();
}
//重新實(shí)現(xiàn)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";
}
//移動(dòng)
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 解析
在重新實(shí)現(xiàn)的重繪事件中,通過QPainter繪制了一系列線組成線串,最后會首尾相連形成多邊形。這里的bMove標(biāo)識是否處于繪制時(shí)的鼠標(biāo)移動(dòng)狀態(tài),只有鼠標(biāo)左鍵點(diǎn)擊后才會確定為真正的節(jié)點(diǎn):
//重新實(shí)現(xiàn)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);
}
}鼠標(biāo)按下事件中,主要是通過bLeftClick值來確定是否已經(jīng)處于左鍵點(diǎn)擊狀態(tài),同時(shí)還能標(biāo)識是否開始進(jìn)行繪制。一旦開始,就會把上次繪制的節(jié)點(diǎn)清除。
//按下
void GraphicsPainter::mousePressEvent(QMouseEvent *e)
{
if(bDraw)
{
if(!bLeftClick)
{
pointList.clear();
bLeftClick = true;
}
}
//qDebug()<<"Press";
}
一旦鼠標(biāo)松開,就可以確定一個(gè)節(jié)點(diǎn),此時(shí)需要調(diào)用update()進(jìn)行重繪:
//松開
void GraphicsPainter::mouseReleaseEvent(QMouseEvent *e)
{
if(bDraw&&bLeftClick)
{
pointList.push_back(QPointF(e->x(), e->y()));
bMove = false;
this->update();
}
//qDebug()<<"Release";
}
當(dāng)開始進(jìn)行繪制后,移動(dòng)鼠標(biāo)就會處于繪制時(shí)的鼠標(biāo)移動(dòng)狀態(tài),這時(shí)就會確定bMove為true,重繪事件就會將該鼠標(biāo)點(diǎn)繪制出來,從而達(dá)到待選節(jié)點(diǎn)的效果:
//移動(dòng)
void GraphicsPainter::mouseMoveEvent(QMouseEvent *e)
{
if(bDraw&&bLeftClick)
{
movePoint = e->pos();
bMove = true;
this->update();
}
//qDebug()<<"Move";
}
鼠標(biāo)雙擊后,將第一個(gè)點(diǎn)加入到當(dāng)前多邊形的節(jié)點(diǎn)中后,達(dá)到首尾相連的效果,此時(shí)就會結(jié)束繪制:
//雙擊
void GraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event)
{
if(bDraw)
{
bLeftClick = false;
pointList.push_back(pointList[0]);
this->update();
singalDrawOver();
}
//qDebug()<<"DoubleClick";
}
這里一定要注意,當(dāng)進(jìn)行雙擊操作時(shí),首先會觸發(fā)一次mousePressEvent,然后觸發(fā)一次mouseReleaseEvent,接著才會觸發(fā)一次mouseDoubleClickEvent,最后還會觸發(fā)一次mouseReleaseEvent。所以這就是這里設(shè)置bLeftClick這個(gè)參數(shù)原因:當(dāng)觸發(fā)mouseDoubleClickEvent后,bLeftClick設(shè)置為false,第二次觸發(fā)mouseReleaseEvent時(shí)內(nèi)部就不會在做任何操作了。
3. 結(jié)果
最終運(yùn)行的結(jié)果如下所示:

到此這篇關(guān)于Qt實(shí)現(xiàn)繪制一個(gè)簡單多邊形的示例代碼的文章就介紹到這了,更多相關(guān)Qt繪制多邊形內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ clock()解析如何使用時(shí)鐘計(jì)時(shí)的應(yīng)用
本篇文章是對c++中的clock()函數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
C/C++函數(shù)參數(shù)聲明解析int?fun()?與?int?fun(void)?的區(qū)別講解
C++中int fun()和int fun(void)的區(qū)別在于函數(shù)參數(shù)的聲明方式,前者默認(rèn)允許任意參數(shù),而后者表示沒有參數(shù),通過清晰的實(shí)例源代碼,詳細(xì)解釋了它們在函數(shù)聲明和調(diào)用中的不同之處,這篇文章介紹了C/C++函數(shù)參數(shù)聲明int?fun()與int?fun(void)的差異,需要的朋友可以參考下2024-01-01
vc6.0中c語言控制臺程序中的定時(shí)技術(shù)(定時(shí)器)
這篇文章主要介紹了vc6.0中c語言控制臺程序中的定時(shí)技術(shù)(定時(shí)器),需要的朋友可以參考下2014-04-04
Windows上Qt配置OpenCV的詳細(xì)教程(避坑必看)
這篇文章詳細(xì)介紹了在Windows上使用Qt配置OpenCV的步驟,包括軟件安裝、環(huán)境變量配置、Qt項(xiàng)目配置以及通過創(chuàng)建pri文件簡化OpenCV庫的添加過程,并提供了一個(gè)簡單的測試案例來驗(yàn)證配置是否成功,需要的朋友可以參考下2025-02-02
C++動(dòng)態(tài)內(nèi)存分配(new/new[]和delete/delete[])詳解
這篇文章主要介紹了C++動(dòng)態(tài)內(nèi)存分配(new/new[]和delete/delete[])詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05
用位圖排序無重復(fù)數(shù)據(jù)集實(shí)例代碼(C++版)
本文講解如何用位圖排序無重復(fù)的數(shù)據(jù)集,我們使用C++實(shí)現(xiàn)一下這個(gè)方法2013-11-11

