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显示图片并且利用鼠标点击画线

  • 16
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 采用Qt库在QLabel控件上显示图片并在图片上画直线的实现步骤如下: 1. 创建一个QLabel控件,并设置其大小和位置。 ```cpp QLabel* label = new QLabel(this); label->setGeometry(0, 0, 300, 300); ``` 2. 加载图片并设置为QLabel的背景。 ```cpp QPixmap pixmap(":/image/image.png"); // 从资源文件中加载图片 QPalette palette; palette.setBrush(label->backgroundRole(), QBrush(pixmap)); label->setPalette(palette); label->setAutoFillBackground(true); ``` 3. 在QLabel上创建一个QPainter对象,并设置画笔的颜色、宽度等属性。 ```cpp QPainter painter(label); painter.setPen(QPen(Qt::red, 2)); // 设置画笔为红色,宽度为2 ``` 4. 使用QPainter在图片绘制直线。 ```cpp painter.drawLine(50, 50, 250, 250); // 在图片绘制一条从(50, 50)到(250, 250)的直线 ``` 5. 更新QLabel控件以显示绘制好的图片。 ```cpp label->update(); ``` 完整代码如下所示: ```cpp #include <QtWidgets> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建主窗体 QWidget window; window.setWindowTitle("Qt Display Image"); window.resize(300, 300); // 创建QLabel控件 QLabel* label = new QLabel(&window); label->setGeometry(0, 0, 300, 300); // 加载图片并设置为QLabel的背景 QPixmap pixmap(":/image/image.png"); // 从资源文件中加载图片 QPalette palette; palette.setBrush(label->backgroundRole(), QBrush(pixmap)); label->setPalette(palette); label->setAutoFillBackground(true); // 在QLabel上创建一个QPainter对象,并设置画笔的颜色、宽度等属性 QPainter painter(label); painter.setPen(QPen(Qt::red, 2)); // 设置画笔为红色,宽度为2 // 使用QPainter在图片绘制直线 painter.drawLine(50, 50, 250, 250); // 在图片绘制一条从(50, 50)到(250, 250)的直线 // 更新QLabel控件以显示绘制好的图片 label->update(); window.show(); return a.exec(); } ``` 以上代码演示了如何使用QtQLabel显示图片并在图片绘制直线。图片加载部分使用了资源文件的方式,即图片需要事先添加到Qt的资源文件中。 ### 回答2: 在Qt中,要在QLabel显示图片并在图片上画直线,您可以按照以下步骤进行操作: 1. 创建一个QLabel对象,并将其设置为一个窗口部件(Widget)的子部件,使用QVBoxLayout进行布局。 ```cpp QLabel *label = new QLabel(this); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(label); this->setLayout(layout); ``` 2. 加载图片到QPixmap对象中,并将其设置到QLabel进行显示。 ```cpp QPixmap pixmap("image.png"); label->setPixmap(pixmap); label->setScaledContents(true); // 自适应QLabel的大小 ``` 3. 创建一个QPainter对象来绘制直线。可以在QLabel的paintEvent事件函数中绘制直线。 ```cpp void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawPixmap(label->geometry(), pixmap); // 在QLabel的范围内绘制图片 // 绘制直线 painter.setPen(Qt::red); // 设置直线颜色为红色 painter.drawLine(50, 50, 200, 200); // 在图片上画一条直线,起点(50, 50),终点(200, 200) } ``` 这样,您就可以在QtQLabel显示图片并在图片绘制直线了。希望对您有所帮助! ### 回答3: 在Qt中,要在QLabel显示图片并在图片上画直线,可以通过以下步骤实现: 1. 创建一个QLabel控件,并设置其大小和位置。 ```cpp QLabel *label = new QLabel(this); label->setGeometry(10, 10, 500, 500); ``` 2. 从文件中加载图片,并将其设置为QLabel的背景。 ```cpp QPixmap pixmap("image.jpg"); label->setPixmap(pixmap); ``` 3. 在QLabel上添加一个QPainter对象,并设置其渲染目标为QLabel。 ```cpp QPainter painter(label); ``` 4. 使用QPen设置画笔的颜色、宽度等属性。 ```cpp QPen pen(Qt::red); pen.setWidth(2); painter.setPen(pen); ``` 5. 使用QPainter在图片上画直线。 ```cpp painter.drawLine(10, 10, 300, 300); ``` 这将在图片上从点(10, 10)绘制一条直线到点(300, 300)。 6. 结束绘制并更新QLabel显示。 ```cpp painter.end(); label->update(); ``` 通过以上步骤,你可以在QtQLabel控件上显示图片并在图片上画直线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值