Qt实现在QLabel上显示图片并进行线条/矩形框/多边形的绘制


前言

本文主要讲述了使用QPainter在QLabel上进行图片的显示,并使用事件过滤器让QLabel捕获QEvent::Paint事件,并结合鼠标事件实现在图片上绘制其它图形。示例代码见文章内容,大家可以参考学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、事件过滤器

Qt的事件过滤器会把控件的绘图事件给过滤,所以不能再任意控件上绘图,为了实现在QLabel上显示图片并在其上进行其它图形的绘制,首先需要给这个控件安装一个事件过滤器,然后重写bool eventFilter(QObject *obj, QEvent *event),代码如下。想要对事件过滤器进行更详细的了解可以参考该博客:Qt 事件过滤器(秒懂)

void Widget::initWidget()
{
    
    
	//...
	//安装事件过滤器
	ui->lb_image->installEventFilter(this);
}

//重写eventFilter
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    
    
    if(watched ==ui->lb_image && event->type() == QEvent::Paint)
    {
    
    
        upPaint();
    }
    return QWidget::eventFilter(watched,event);
}

二、示例完整代码展示

1.widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPoint>
#include <QPen>
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
#include <QDir>

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    
    
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void initWidget();
    void upPaint();

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);

private slots:
    void on_pb_line_1_clicked();
    void on_pb_line_2_clicked();
    void on_pb_rect_clicked();
    void on_pb_show_clicked();
    void on_pb_clear_clicked();

private:
    Ui::Widget *ui;

    bool isPressed;

    //line1
    int lineNum;
    bool lineFlag1;
    QPoint linePoint[5];

    //line2
    bool lineFlag2;
    QPoint lineStartPoint;
    QPoint lineEndPoint;

    //rect
    bool rectFlag;
    int rect[4] = {
    
    0};

};
#endif // WIDGET_H

2.widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    
    
    ui->setupUi(this);
    this->initWidget();
}

Widget::~Widget()
{
    
    
    delete ui;
}

void Widget::initWidget()
{
    
    
    isPressed = false;

    lineNum = 0;
    lineFlag1 = false;
    for(int i=0;i<5;i++)
    {
    
    
        linePoint[i] = QPoint(0,0);
    }

    lineFlag2 = false;
    lineStartPoint = QPoint(0,0);
    lineEndPoint = QPoint(0,0);

    rectFlag = false;

    ui->lb_image->installEventFilter(this);
}

void Widget::upPaint()     //绘图
{
    
        
    QPainter painter(ui->lb_image);
    //显示图片
    QString imagePath = "E:/PhotoTest/drawTest.PNG";   //图片对应路径
    painter.drawPixmap(0,0,400,300,QPixmap(imagePath));

    //显示图片的另一种方法:setPixmap,这里不要使用
    //QImage Image;
    //Image.load(imagePath);
    //ui->lb_image->setPixmap(QPixmap::fromImage(Image));

    QPen pen;
    pen.setColor(Qt::red);
    painter.setPen(pen);
    painter.drawRect(1,1,100,50);
    painter.drawText(10,30,"测试文字");

    if(lineFlag1)   //line1
    {
    
    
        if(lineNum == 2)
        {
    
    
            painter.drawLine(linePoint[0],linePoint[1]);
        }
        else if(lineNum == 3)
        {
    
    
            painter.drawLine(linePoint[0],linePoint[1]);
            painter.drawLine(linePoint[1],linePoint[2]);
        }
        else if(lineNum == 4)
        {
    
    
            painter.drawLine(linePoint[0],linePoint[1]);
            painter.drawLine(linePoint[1],linePoint[2]);
            painter.drawLine(linePoint[2],linePoint[3]);
        }
        else if(lineNum == 5)
        {
    
    
            painter.drawLine(linePoint[0],linePoint[1]);
            painter.drawLine(linePoint[1],linePoint[2]);
            painter.drawLine(linePoint[2],linePoint[3]);
            painter.drawLine(linePoint[3],linePoint[4]);
        }
        else if(lineNum == 6)
        {
    
    
            painter.drawLine(linePoint[0],linePoint[1]);
            painter.drawLine(linePoint[1],linePoint[2]);
            painter.drawLine(linePoint[2],linePoint[3]);
            painter.drawLine(linePoint[3],linePoint[4]);
            painter.drawLine(linePoint[4],linePoint[0]);
        }
    }
    if(lineFlag2)   //line2
    {
    
    
        painter.drawLine(lineStartPoint,lineEndPoint);
    }
    if(rectFlag)   //line2
    {
    
    
        painter.drawRect(rect[0],rect[1],rect[2],rect[3]);
    }

    //p.drawLine(QLine(100,100,100,250));
    //painter.drawRect(100,100,200,150);
}

//鼠标按下
void Widget::mousePressEvent(QMouseEvent *event)
{
    
    
    if(event->button() == Qt::LeftButton)
    {
    
    
        isPressed = true;
        if(lineFlag2)
        {
    
    
            lineStartPoint = QPoint(event->pos().x()-30,event->pos().y()-30);
            lineEndPoint = QPoint(event->pos().x()-30,event->pos().y()-30);
        }
        else if(rectFlag)
        {
    
    
            rect[0] = event->pos().x()-30;
            rect[1] = event->pos().y()-30;
        }
    }
}

//鼠标移动
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    
    
    if(isPressed)
    {
    
    
        if(lineFlag2)
        {
    
    
            lineEndPoint = QPoint(event->pos().x()-30,event->pos().y()-30);
        }
        else if(rectFlag)
        {
    
    
            rect[2] = event->pos().x()-30 - rect[0];
            rect[3] = event->pos().y()-30 - rect[1];
        }
        this->update();
    }
}

//鼠标抬起
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    
    
    qDebug()<<"Release:"<<QPoint(event->pos().x()-30,event->pos().y()-30);
    if(event->button() == Qt::LeftButton)
    {
    
    
        if(lineFlag1)
        {
    
    
            //多个点(以5个点示例)
            if(lineNum == 0)
            {
    
    
                lineNum = 1;
                linePoint[0] = QPoint(event->pos().x()-30,event->pos().y()-30);
                this->update();
            }
            else if(lineNum == 1)
            {
    
    
                lineNum = 2;
                linePoint[1] = QPoint(event->pos().x()-30,event->pos().y()-30);
                this->update();
            }
            else if(lineNum == 2)
            {
    
    
                lineNum = 3;
                linePoint[2] = QPoint(event->pos().x()-30,event->pos().y()-30);
                this->update();
            }
            else if(lineNum == 3)
            {
    
    
                lineNum = 4;
                linePoint[3] = QPoint(event->pos().x()-30,event->pos().y()-30);
                this->update();
            }
            else if(lineNum == 4)
            {
    
    
                lineNum = 5;
                linePoint[4] = QPoint(event->pos().x()-30,event->pos().y()-30);
                this->update();
            }
            else if(lineNum == 5)
            {
    
    
                lineNum = 6;
                this->update();
            }
            else
            {
    
    
                lineNum = 0;
                this->update();
            }
        }
        else if(lineFlag2)
        {
    
    
            isPressed=false;
            lineEndPoint = QPoint(event->pos().x()-30,event->pos().y()-30);
            this->update();
        }
        else if(rectFlag)
        {
    
    
            isPressed=false;
            rect[2] = event->pos().x()-30 - rect[0];
            rect[3] = event->pos().y()-30 - rect[1];
            this->update();
        }
    }
    else if(event->button() == Qt::RightButton)
    {
    
    
        isPressed=false;
        lineNum = 0;
        lineFlag1 = false;
        lineFlag2 = false;
        rectFlag = false;
        this->update();
    }
}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    
    
    if(watched ==ui->lb_image && event->type() == QEvent::Paint)
    {
    
    
        upPaint();
    }
    return QWidget::eventFilter(watched,event);
}

void Widget::on_pb_line_1_clicked()
{
    
    
    lineFlag1 = true;
    lineFlag2 = false;
    rectFlag = false;
    this->update();
}

void Widget::on_pb_line_2_clicked()
{
    
    
    lineFlag1 = false;
    lineFlag2 = true;
    rectFlag = false;
    this->update();
}

void Widget::on_pb_rect_clicked()
{
    
    
    lineFlag1 = false;
    lineFlag2 = false;
    rectFlag = true;
    this->update();
}

void Widget::on_pb_show_clicked()
{
    
    
    lineFlag1 = true;
    lineFlag2 = true;
    rectFlag = true;
    this->update();
}

void Widget::on_pb_clear_clicked()
{
    
    
    isPressed = false;

    lineNum = 0;
    lineFlag1 = false;
    for(int i=0;i<5;i++)
    {
    
    
        linePoint[i] = QPoint(0,0);
    }

    lineFlag2 = false;
    lineStartPoint = QPoint(0,0);
    lineEndPoint = QPoint(0,0);

    rectFlag = false;
    for(int i=0;i<4;i++)
    {
    
    
        rect[i] = 0;
    }

    this->update();
}

3.widget.ui请添加图片描述

三、下载链接

我的示例百度网盘链接:https://pan.baidu.com/s/1wJj8UHgr7Aub-7p8pojnrw
提取码:xxcj


总结

本文示例使用到了Qt的事件过滤器并重写了QPaintEvent、QMouseEvent等事件,这也是比较常见的方式。在我们之后的工作中,要学会灵活使用事件系统来实现自己的需求。示例中要注意的一点,这里在QLabel上显示图片需要使用QPainter中的drawPixmap,而不能使用QLabel的setPixmap方法,不然在进行绘制线条时出现无法显示的情况(其实是绘制出来了,但是被图片挡住了)。


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考博客:
Qt 事件过滤器(秒懂)
QT中在QLabel显示图片并且利用鼠标点击画线

猜你喜欢

转载自blog.csdn.net/XCJandLL/article/details/127458147