QLabel中的GIF图像

7

我想在QLabel中添加一个gif动画图像,并将其添加到QGraphicsScene中。 我的代码如下:

QLabel *lbl = new QLabel;
QMovie *mv = new QMovie(":/Images/sun.gif");
mv->start();
lbl->setWindowFlags(Qt::FramelessWindowHint);
lbl->setMask((new QPixmap(":/Images/sun.gif"))->mask());   // for create transparent for QLabel image
lbl->setMovie(mv);
lbl->setGeometry(10,10,10,10);
scene.addWidget(lbl);

当我运行它时,它将与gif的第一帧呈透明状态,当gif正在运行时,照片将不完全显示,并且会在第一帧中带有透明区域。如何解决这个问题?

谢谢。


你需要将你的gif转换成mng格式。 - r3wt
你能发布GIF文件进行测试吗? - Pavel Strakhov
@PavelStrakhov https://drive.google.com/file/d/0B8MHb_yB30noSVl4VnJEWEExQzQ/edit?usp=sharing - Rmin
似乎上面的链接已经失效了。更新的链接(如果需要): https://drive.google.com/file/d/0B8MHb_yB30noSVl4VnJEWEExQzQ/view?usp=sharing&resourcekey=0-C4cYJ_erWOD_DchwPU_FkQ - Rmin
1个回答

7
问题在于QLabel默认具有窗口背景。您试图通过不正确的方式来删除它:

FramelessWindowHint在这里没有意义,因为它仅用于顶级小部件,并且添加到场景中的小部件在技术上是隐藏的,没有系统窗口框架。应该删除此行。

setMask正好做了您所描述的操作。由于QPixmap不是动画的,其掩码是动画的第一帧的Alpha掩码。而且您永久地将此掩码应用于标签。这似乎能够正常工作,但显然不是您想要的。也应该删除此行。

setGeometry的代码行是不正确的。对我而言,它会阻止图片的可见性。默认情况下,标签的大小很好,不需要使用setGeometry。如果您想要缩放或移动场景上的项目,则可以像其他任何QGraphicsItem一样在addWidget之后进行操作。例如:addWidget(lbl)->setPos(10, 10)

您需要的"魔法子弹"是WA_NoSystemBackground。它完全禁用了QLabel的背景绘制。因此,完整的代码将是:

QLabel *lbl = new QLabel;
QMovie *mv = new QMovie("c:/tmp/sun.gif");
mv->start();
lbl->setAttribute(Qt::WA_NoSystemBackground);
lbl->setMovie(mv);
scene.addWidget(lbl);

这对我来说工作得很好。然而,我认为它过于复杂了。除非必要,否则不应在场景中使用代理小部件。您可以使用QMovieQGraphicsPixmapItem轻松添加电影,并在电影帧更改时切换像素图。我为此编写了一个方便的类:

头文件:

class GraphicsMovieItem : public QObject, public QGraphicsPixmapItem {
  Q_OBJECT
public:
  GraphicsMovieItem(QGraphicsItem* parent = 0);
  void setMovie(QMovie* movie);

private:
  QMovie* m_movie;

private slots:
  void frameChanged();
};

来源:

GraphicsMovieItem::GraphicsMovieItem(QGraphicsItem *parent)
  : QGraphicsPixmapItem(parent), m_movie(0) {
}

void GraphicsMovieItem::setMovie(QMovie *movie) {
  if (m_movie) {
    disconnect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged()));
  }
  m_movie = movie;
  if (m_movie) {
    connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frameChanged()));
  }
  frameChanged();
}

void GraphicsMovieItem::frameChanged() {
  if (!m_movie) { return; }
  setPixmap(m_movie->currentPixmap());
}

使用方法:

QMovie *mv = new QMovie("c:/tmp/sun.gif");
GraphicsMovieItem* item = new GraphicsMovieItem();
item->setMovie(mv);
scene.addItem(item);

如果答案解决了你的问题,你应该接受它。 - Pavel Strakhov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接