开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
摘要
本文叙述的这个坑固然重要,更重要的是遇到问题,一步步分析的思路。作为程序员,遇到问题是在所难免的,如何快速的分析问题、定位问题,比解决问题更重要。
背景
自定义一个Widget用于显示图片,并实现单击图片时,放大图片。基于此,实现方案为自定义一个widget,并内置一个QLabel,通过QLabel来显示图片,并通过事件过滤器,响应QLabel控件的单击事件,创建新的界面,显示图片。在应用时将QWidget控件提升为自定义的界面类。
具体的代码如下
//.h头文件
#ifndef CRESOURCEDISPLAYWGT_H
#define CRESOURCEDISPLAYWGT_H
#include <QWidget>
namespace Ui {
class CResourceDisplayWgt;
}
class CResourceDisplayWgt : public QWidget
{
Q_OBJECT
public:
explicit CResourceDisplayWgt(QWidget *parent = nullptr);
~CResourceDisplayWgt();
protected:
virtual bool eventFilter(QObject *watch, QEvent *event)override;
public:
QString addResourcebyName(const QString& name);
private:
Ui::CResourceDisplayWgt *ui;
QString m_resource_path{""};
};
#endif // CRESOURCEDISPLAYWGT_H
//.cpp文件
#include "CResourceDisplayWgt.h"
#include "ui_CResourceDisplayWgt.h"
#include <QMouseEvent>
#include<QDebug>
#include <QFileInfo>
#include<QPixmap>
CResourceDisplayWgt::CResourceDisplayWgt(QWidget *parent) :
QWidget(parent),
ui(new Ui::CResourceDisplayWgt)
{
ui->setupUi(this);
ui->label_Picture->installEventFilter(this);
}
CResourceDisplayWgt::~CResourceDisplayWgt()
{
delete ui;
}
bool CResourceDisplayWgt::eventFilter(QObject *watch, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
auto mouseEvent = static_cast<QMouseEvent*>(event);
if(mouseEvent && mouseEvent->button() == Qt::LeftButton&& watch == ui->label_Picture)
{
//创建展示图片展示的界面CPictureDisplayWgt,
//设置图片路径
//CPictureDisplayWgt->show();
return true;
}
}
//return QWidget::eventFilter(watch,event);//这就是出现错误地方法
}
QString CResourceDisplayWgt::addResourcebyName(const QString &name)
{
//qDebug()<<__func__<<name;
QPixmap picMap;
if (!picMap.load(name))
{
return "";
}
m_resource_path = name;
auto size = ui->label_Picture->size();
auto p = picMap.scaled(size,Qt::KeepAspectRatio);//缩放图片到label的尺寸
//p.save("d://22.jpg");//保存该图片
//qDebug()<<p.isNull();//判断图片是否为空
ui->label_Picture->setPixmap(p);
qDebug()<<ui->label_Picture->size();
//qDebug()<<ui->label_Picture->pixmap()->save("d://333.jpg");//查看设置的该图片是否正确
//qDebug()<<ui->label_Picture->size();//打印该label的尺寸,判断是否label为(0,0)所以不显示
}
问题
在实际应用时,调用该界面类的addResourcebyName方法,设置图片后,一直不显示图片。
分析本文重点
-
图片的路径是否正确的设置到该函数
- 打印路径
-
设置的路径是否指向一个图片文件
- 通过QPixmap的load方法查看图片是否加载成功
-
缩放后的图片是否是正确的(由于将图片放置到QLabel所以有缩放)
- 保存缩放后的图片
-
查看QLabel控件的位置和尺寸
- 通过QLabel的位置可以知晓:图片是否在其他地方显示
- QLabel的尺寸可以知晓,是否为QSize为(0,0)而无法显示图片
-
查看设置到QLabel中的图片是否是正确
- 通过QLabel的pixmap函数获得设置到QLabel控件中的图片,并将其保存成文件
通过以上分析,答案均为正确,图片未显示着实有些蹊跷
-
控件是否被正确绘制了
- 为此,还特意调用update函数,希望调用整个界面的绘制函数,但是仍旧无法得到显示图片。那是否是没有调用执行paintEvent事件呢
-
手动绘制图片
- 重载paintEvent事件,在该函数中绘制图片,图片显示成功
反思,重载绘制事件后,图片可以正确显示,那么重载之前为何无法显示图片呢,也就是说之前的paint事件未被正确执行,那也就找到答案了,eventFilter函数使用不当
解惑
为此,查看eventFilter函数,帮助文档的描述如下
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
Filters events if this object has been installed as an event filter for the watched object.
In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false.
释义:如果想要将事件过滤掉,不再向上传递,return true,否则返回false,
而我的用法中未返回任何值,导致图片一直显示不出来。
解决方法
将eventFilter函数返还给其父类,不用实现paintEvent事件,也可以正确显示图片。