解决Qt重绘事件中进行了耗时的图片操作导致卡顿问题
先简单描述一下我出现的问题,我是在写一个聊天界面,然后对于图片消息来说,一旦图片比较大时,滑动聊天界面就会出现了明显卡顿情况,原因是和我在写这个ImageMessage时直接在paintEvent中就进行了耗时的图片操作,也是我对于重绘事件的不够了解导致的在c++ - Stabilize QWidget::paintEvent() calls frequency - Stack Overflow
QWidget Class | Qt Widgets | Qt 6.9.1中可以看到.大致告诉我们在paintEvent中不要进行一些其他的操作,他只负责绘制.
我这个MessageImage就是左下角这个长矩形,有点难度的地方在这个如何计算图片放置的位置,需要用到父元素来计算,我在解决卡顿时把updateUi从paintEvent直接提出来就出现了父元素为NULL,因为我使用MessageImage没有直接传父元素给构造函数,而是先创建在放入layout中,也就导致了更新ui时出现父元素为空的情况,然后我采用的是新增一个字段表示是否完成ui更新,updateUI将state设置为false__updateUi在父元素为空时会直接返回没有更新图片和state,然后让showEvent去再判断是否成功了,没成功再执行 一次 updateUi,这样就将原本卡顿的显示解决了.
class MessageImage : public QWidget {
Q_OBJECT
public:
MessageImage(const QString& fileId,const QByteArray& content, bool isLeft);
void updateUI(const QString& fileId, const QByteArray& content);
protected:
void paintEvent(QPaintEvent* event) override;
void showEvent(QShowEvent* event) override;
private:
void __updateUi();
private:
QPushButton* image;
QString fileId;
QPixmap image_pixmap;
bool isLeft;
bool state; // 0 -- 未更新
};
//==========================================================================================
MessageImage::MessageImage(const QString& fileId, const QByteArray& content, bool isLeft)
:isLeft(isLeft),fileId(fileId),state(false)
{
this->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
this->setStyleSheet("QPushButton{border:none;} QWidget{background-color:red}");
image = new QPushButton(this);
if (content.isEmpty()) {
model::DataCenter* dataCenter = model::DataCenter::getInstance();
connect(dataCenter, &model::DataCenter::getSingleFileDone, this,&MessageImage::updateUI,Qt::UniqueConnection);
dataCenter->getSingleFileAsync(fileId);
}
else {
updateUI(fileId, content);
}
}
void MessageImage::updateUI(const QString& fileId, const QByteArray& content)
{
if (this->fileId.isEmpty() || content.isEmpty()) {
return;
}
this->fileId = fileId;
__scaledImageToWidth(content, image_pixmap);
this->state = false;
__updateUi();
this->update();
}
void MessageImage::showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
if (!state) {
__updateUi();
}
}
void MessageImage::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QWidget::paintEvent(event);
}
void __scaledImageToWidth(const QByteArray& body,__out QPixmap& pixmap) {
pixmap.loadFromData(body);
pixmap = pixmap.scaledToWidth(120, Qt::SmoothTransformation);
}
void MessageImage::__updateUi() {
QObject* obj = this->parent();
if (obj == nullptr || !obj->isWidgetType()) {
return;
}
QWidget* parent = dynamic_cast<QWidget*> (obj);
if (image_pixmap.isNull()) {
image_pixmap.load(":/resource/images/xiaoju.jpg");
}
QRect r = image_pixmap.rect();
qDebug() << "image rect " << r;
parent->setMinimumHeight(r.height() + 30);
image->setIconSize(QSize(r.width(), r.height()));
image->setIcon(QIcon(image_pixmap));
if (isLeft) {
image->setGeometry(0, 0, r.width(), r.height());
}
else {
image->setGeometry(parent->width() - r.width() - 65, 0, r.width(), r.height());
}
this->state = true;
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]