【问题标题】:How to set animated icon to QPushButton in Qt5?如何在 Qt5 中将动画图标设置为 QPushButton?
【发布时间】:2023-03-08 03:09:02
【问题描述】:

QPushButton 可以有图标,但我需要为其设置动画图标。这个怎么做? 我创建了从QPushButton 实现的新类,但是如何将图标从QIcon 替换为QMovie

【问题讨论】:

    标签: qt animation icons qt5 qpushbutton


    【解决方案1】:

    由于我今天必须为我的一个项目解决这个问题,我只是想放弃我为未来的人找到的解决方案,因为这个问题有很多观点,我认为该解决方案非常优雅。解决方案已发布here。每次设置pushButton的图标,QMovie的frame都会改变:

    auto movie = new QMovie(this);
    movie->setFileName(":/sample.gif");
    connect(movie, &QMovie::frameChanged, [=]{
      pushButton->setIcon(movie->currentPixmap());
    });
    movie->start();
    

    这还有一个好处,就是图标在 QMovie 启动之前不会出现。这也是我为我的项目派生的python解决方案:

    #'hide' the icon on the pushButton
    pushButton.setIcon(QIcon())
    animated_spinner = QtGui.QMovie(":/icons/images/loader.gif")
    animated_spinner.frameChanged.connect(updateSpinnerAniamation)           
    
    def updateSpinnerAniamation(self):
      #'hide' the text of the button
      pushButton.setText("")
      pushButton.setIcon(QtGui.QIcon(animated_spinner.currentPixmap()))
    

    一旦你想显示微调器,只需启动 QMovie:

    animated_spinner.start()
    

    如果微调器再次消失,则停止动画并再次“隐藏”微调器。一旦动画停止,frameChanged 插槽将不再更新按钮。

    animated_spinner.stop()
    pushButton.setIcon(QtGui.QIcon())
    

    【讨论】:

      【解决方案2】:

      这可以在不继承QPushButton 的情况下通过简单地使用Qt 的信号/槽机制来完成。将QMovieframeChanged 信号连接到包含此QPushButton 的类中的自定义槽。此函数将QMovie 的当前帧应用为QPushButton 的图标。它应该看起来像这样:

      // member function that catches the frameChanged signal of the QMovie
      void MyWidget::setButtonIcon(int frame)
      {
          myPushButton->setIcon(QIcon(myMovie->currentPixmap()));
      }
      

      在分配您的QMovieQPushButton 成员时...

      myPushButton = new QPushButton();
      myMovie = new QMovie("someAnimation.gif");
      
      connect(myMovie,SIGNAL(frameChanged(int)),this,SLOT(setButtonIcon(int)));
      
      // if movie doesn't loop forever, force it to.
      if (myMovie->loopCount() != -1)
          connect(myMovie,SIGNAL(finished()),myMovie,SLOT(start()));
      
      myMovie->start();
      

      【讨论】:

      • 非常感谢。动画图片可以有透明背景吗?
      • 据我所知你应该可以。 GIF 格式允许透明(通过在图像中指定应该透明的颜色),Qt 允许在小部件上绘制透明的 QPixmap。我唯一不确定的是 QMovie 是否支持透明度。由于 Qt 类通常非常彻底,如果 QMovie 不支持透明度,我会感到惊讶,但它在文档中没有提及这一点。
      • 我需要两个动画图标并根据情况进行更改(空闲时 - 一个,工作时 - 另一个)。我怎样才能优雅地做到这一点?
      • 好吧,我要做的是声明两个插槽;一部用于工作状态电影,一部用于空闲状态电影。然后在切换状态时,只需在前一个状态的电影上调用 stop() 并在新状态的电影上调用 start() 。由于之前状态的电影不会“正在播放”,因此在您再次开始播放之前,不会调用其插槽。
      • 我觉得两槽解决方案不太优雅。我更喜欢继承 QPushButton 并在内部处理帧更改,并使用自定义方法 setMovie 切换图标。我认为这会更优雅且与 OOP 一致。
      猜你喜欢
      • 1970-01-01
      • 2014-03-08
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      • 2020-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多