在 PyQt5 的 QMessageBox 中使用动画 QIcon?

问题描述 投票:0回答:1

我想要我的 QMessageBox 的动画图标 - 我发现 QtAwesome 有一个漂亮的动画微调器。

所以我尝试了这个非常简单的例子:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
import qtawesome as qta

class Example(QWidget):
  def __init__(self):
    super().__init__()
    self.initUI()

  def initUI(self):
    self.setGeometry(300, 300, 300, 220)
    self.setWindowTitle('Hello World')
    self.show()
    msgBox = QMessageBox( QMessageBox.NoIcon, "Title", "Content ...", QMessageBox.Cancel )
    animation = qta.Spin(msgBox)
    spin_icon = qta.icon('fa5s.spinner', color='red', animation=animation)
    msgBox.setIcon(spin_icon)
    returnValue = msgBox.exec()

if __name__ == '__main__':
  app = QApplication(sys.argv)
  ex = Example()
  sys.exit(app.exec_())

...但是,不幸的是它崩溃了:

$ python3 my_qttest.py
Traceback (most recent call last):
  File "C:/msys64/tmp/my_qttest.py", line 23, in <module>
    ex = Example()
         ^^^^^^^^^
  File "C:/msys64/tmp/my_qttest.py", line 9, in __init__
    self.initUI()
  File "C:/msys64/tmp/my_qttest.py", line 18, in initUI
    msgBox.setIcon(spin_icon)
TypeError: setIcon(self, a0: QMessageBox.Icon): argument 1 has unexpected type 'QIcon'

嗯,我有点以为

.setIcon
会接受 QIcon 对象,但实际上它不接受 - https://doc.qt.io/qt-5/qmessagebox.html 注意到 QMessageBox::Icon 实际上是一个枚举(不是一堂课,正如我一开始所想的):

Constant                Value   Description
QMessageBox::NoIcon     0       the message box does not have any icon.
QMessageBox::Question   4       an icon indicating that the message is asking a question.
...

...然而,

qta.icon
返回一个
QIcon

那么,我如何为 QMessageBox 使用动画 QIcon?

pyqt5
1个回答
0
投票

感谢@eyllanesc 的评论

尝试:

msgBox.setIconPixmap(icon.pixmap())

...我终于成功了:

...虽然它并不像评论所暗示的那么微不足道,所以我将在此答案中发布详细信息:

  • 使用
    .pixmap()
    方法检索像素图实际上需要一个大小 - 所以我们想要使用最初在 QMessageBox 中使用的像素图大小
  • 请注意,如果我们像OP中那样使用
    QMessageBox.NoIcon
    ,我们将读取0,0的像素图大小,这是不可用的 - 因此我们必须使用其他一些普通的QMessageBox图标进行初始化,以便我们可以检索它们的原始像素图大小
  • 即使我们设法做到
    setIconPixmap
    ,也只会显示单个图像,而不是动画 - 要使动画正常工作,我们必须对 QtAwesome
    Spin
    实例的
    _update
    方法进行猴子修补,并执行
    setIconPixmap 
    从那里

总而言之,代码现在是这样的:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox
from PyQt5.QtCore import Qt, QPoint, QRect
import qtawesome as qta

class Example(QWidget):
  def __init__(self):
    super().__init__()
    self.initUI()

  def initUI(self):
    self.setGeometry(300, 300, 300, 220)
    self.setWindowTitle('Hello World')
    self.show()
    msgBox = QMessageBox( QMessageBox.Information, "Title", "Content ...", QMessageBox.Cancel )
    msg_newpos_geom = QRect(QPoint(350,350), msgBox.sizeHint())
    msgBox.move(msg_newpos_geom.topLeft())
    orig_ipmsize = msgBox.iconPixmap().size()
    print(orig_ipmsize.width(), orig_ipmsize.height()) # 0 0 for QMessageBox.NoIcon; 32 32 for QMessageBox.Information
    animation = qta.Spin(msgBox, autostart=True)
    spin_icon = qta.icon('fa5s.spinner', color='red', animation=animation)
    # msgBox.setIconPixmap(spin_icon.pixmap(orig_ipmsize)) #msgBox.setIcon(spin_icon) # if this statement is enabled/running here, it prevents new_anim_update from running!

    # this is DO_MONKEYPATCH = 1 approach from https://stackoverflow.com/q/78325356 :
    old_anim_update = animation._update
    def new_anim_update(self):
      old_anim_update() # no error
      #print("new_anim_update {}".format(self)) # self is <qtawesome.animation.Spin object at 0x00000238f1d45f10>
      msgBox.setIconPixmap(spin_icon.pixmap(orig_ipmsize))
    animation._update = new_anim_update.__get__(animation, qta.Spin) # https://stackoverflow.com/a/28127947

    #print(animation._update)
    msgBox.setIconPixmap(spin_icon.pixmap(orig_ipmsize)) #msgBox.setIcon(spin_icon)
    #animation.start()
    returnValue = msgBox.exec()

if __name__ == '__main__':
  app = QApplication(sys.argv)
  ex = Example()
  sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.