文章目录
前言
本文主要讲述了使用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:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。