找回密码
 立即注册
首页 业界区 安全 解决Qt重绘事件中进行了耗时的图片操作导致卡顿问题 ...

解决Qt重绘事件中进行了耗时的图片操作导致卡顿问题

余思洁 3 天前
先简单描述一下我出现的问题,我是在写一个聊天界面,然后对于图片消息来说,一旦图片比较大时,滑动聊天界面就会出现了明显卡顿情况,原因是和我在写这个ImageMessage时直接在paintEvent中就进行了耗时的图片操作,也是我对于重绘事件的不够了解导致的
在c++ - Stabilize QWidget::paintEvent() calls frequency - Stack Overflow
QWidget Class | Qt Widgets | Qt 6.9.1中可以看到.大致告诉我们在paintEvent中不要进行一些其他的操作,他只负责绘制.
1.png

我这个MessageImage就是左下角这个长矩形,有点难度的地方在这个如何计算图片放置的位置,需要用到父元素来计算,我在解决卡顿时把updateUi从paintEvent直接提出来就出现了父元素为NULL,因为我使用MessageImage没有直接传父元素给构造函数,而是先创建在放入layout中,也就导致了更新ui时出现父元素为空的情况,然后我采用的是新增一个字段表示是否完成ui更新,updateUI将state设置为false__updateUi在父元素为空时会直接返回没有更新图片和state,然后让showEvent去再判断是否成功了,没成功再执行 一次 updateUi,这样就将原本卡顿的显示解决了.
  1. class MessageImage : public QWidget {
  2.         Q_OBJECT
  3. public:
  4.         MessageImage(const QString& fileId,const QByteArray& content, bool isLeft);
  5.         void updateUI(const QString& fileId, const QByteArray& content);
  6. protected:
  7.         void paintEvent(QPaintEvent* event) override;
  8.     void showEvent(QShowEvent* event) override;
  9. private:
  10.     void __updateUi();
  11. private:
  12.         QPushButton* image;
  13.         QString fileId;
  14.     QPixmap image_pixmap;
  15.         bool isLeft;
  16.     bool state; // 0 -- 未更新
  17. };
  18. //==========================================================================================
  19. MessageImage::MessageImage(const QString& fileId, const QByteArray& content, bool isLeft)
  20.         :isLeft(isLeft),fileId(fileId),state(false)
  21. {
  22.         this->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
  23.         this->setStyleSheet("QPushButton{border:none;} QWidget{background-color:red}");
  24.     image = new QPushButton(this);
  25.     if (content.isEmpty()) {
  26.                 model::DataCenter* dataCenter = model::DataCenter::getInstance();
  27.                 connect(dataCenter, &model::DataCenter::getSingleFileDone, this,&MessageImage::updateUI,Qt::UniqueConnection);
  28.                 dataCenter->getSingleFileAsync(fileId);
  29.     }
  30.     else {
  31.         updateUI(fileId, content);
  32.     }
  33. }
  34. void MessageImage::updateUI(const QString& fileId, const QByteArray& content)
  35. {
  36.     if (this->fileId.isEmpty() || content.isEmpty()) {
  37.         return;
  38.     }
  39.     this->fileId = fileId;
  40.     __scaledImageToWidth(content, image_pixmap);
  41.     this->state = false;
  42.     __updateUi();
  43.         this->update();
  44. }
  45. void MessageImage::showEvent(QShowEvent* event)
  46. {
  47.     QWidget::showEvent(event);
  48.     if (!state) {
  49.         __updateUi();  
  50.     }
  51. }
  52. void MessageImage::paintEvent(QPaintEvent* event)
  53. {
  54.     Q_UNUSED(event);
  55.     QWidget::paintEvent(event);
  56. }
  57. void __scaledImageToWidth(const QByteArray& body,__out QPixmap& pixmap) {
  58.     pixmap.loadFromData(body);
  59.     pixmap = pixmap.scaledToWidth(120, Qt::SmoothTransformation);
  60. }
  61. void MessageImage::__updateUi() {
  62.     QObject* obj = this->parent();
  63.     if (obj == nullptr || !obj->isWidgetType()) {
  64.         return;
  65.     }
  66.     QWidget* parent = dynamic_cast<QWidget*> (obj);
  67.     if (image_pixmap.isNull()) {
  68.         image_pixmap.load(":/resource/images/xiaoju.jpg");
  69.     }
  70.     QRect r = image_pixmap.rect();
  71.     qDebug() << "image rect " << r;
  72.     parent->setMinimumHeight(r.height() + 30);
  73.     image->setIconSize(QSize(r.width(), r.height()));
  74.     image->setIcon(QIcon(image_pixmap));
  75.     if (isLeft) {
  76.         image->setGeometry(0, 0, r.width(), r.height());
  77.     }
  78.     else {
  79.         image->setGeometry(parent->width() - r.width() - 65, 0, r.width(), r.height());
  80.     }
  81.     this->state = true;
  82. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册