当前位置: 移动技术网 > IT编程>开发语言>C/C++ > 使用QT绘制一个多边形

使用QT绘制一个多边形

2020年03月09日  | 移动技术网IT编程  | 我要评论

意大利经典慢摇,与你共坠爱河,赛尔号哈莫雷特在哪打

目录

1. 概述

可以通过qt的重绘事件和鼠标事件来绘制多边形,最简单的办法就是在继承qwidget的窗体中重写paintevent、mousepressevent等事件处理函数。qt提供了图形绘制接口qpainter,通过该接口可以绘制多种图形,包括多边形。

2. 实现

2.1. 代码

新建一个基于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);        //移动
    void mousereleaseevent(qmouseevent *e);     //松开
    void mousedoubleclickevent(qmouseevent *event);        //双击


    bool bdraw;             //是否处于绘制状态
    bool bleftclick;            //是否已经开始左键点击,同时标识是否开始进行绘制
    bool bmove;             //是否处于绘制时的鼠标移动状态

    qvector<qpointf> pointlist;
    qpointf movepoint;
};

#endif // graphicspainter_h

graphicspainter.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();
}

//重新实现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标识是否处于绘制时的鼠标移动状态,只有鼠标左键点击后才会确定为真正的节点:

//重新实现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";
}

鼠标双击后,将第一个点加入到当前多边形的节点中后,达到首尾相连的效果,此时就会结束绘制:

//双击
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绘制多边形

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网