【问题标题】:Can't refesh pixmap of QLabel无法刷新 QLabel 上的像素图
【发布时间】:2015-06-08 21:18:00
【问题描述】:

我已经在这个问题上停留了 2 天。我在Window 7-64 bit 上为Visual Studio 2013 使用Qt 插件。

我一直在尝试在QLabels 中显示一对图像。我需要定期操作像素数据,所以我将它们存储在QImages 中,每次我想刷新显示时我设置QPixmapQLabel。问题是,如果我以某种方式更改/移动窗口,它似乎只会刷新。

如果我只是将QLabels 设为我的QWidget 的子级,但从不设置布局,这个问题就会消失。如果我再添加repaint()update(),问题又回来了。

(这与我使用QGraphicsScene 发布的帖子非常相似,但问题似乎比这更根本,所以我重新发布)

这是我的代码。首先是 .h

#ifndef DISPLAYWIDGET_H
#define DISPLAYWIDGET_H

#include <QtWidgets/QWidget>
#include <QPixmap>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QPushButton>
#include <QHBoxLayout>
#include <QTimer>
#include <QLabel>

#define FULLSCALE 255
#define IM_X_MIN -5.0
#define IM_X_MAX 5.0
#define IM_Z_MIN 0.0
#define IM_Z_MAX 15.0
#define IM_PIXEL_WIDTH 200
#define IM_PIXEL_HEIGHT IM_PIXEL_WIDTH * (IM_Z_MAX-IM_Z_MIN)/(IM_X_MAX - IM_X_MIN)
#define BORDER_WIDTH    10
#define RAND_SEED 7

class DisplayWidget : public QWidget
{
    Q_OBJECT

public:
    DisplayWidget(int width, int height, QWidget *parent = 0);
    ~DisplayWidget();

private:
    QLabel* bimageLabel;
    QLabel* dimageLabel;
    QImage* bImage;
    QImage* dImage;
    QTimer* frameGrab;
    QPushButton* debugButton;

    void CreateWidgets();
    void SetupGui();

    int w, h;

public slots:
    void GenerateNewData();
};

#endif // DISPLAYWIDGET_H

和 .cpp。

#include "displaywidget.h"

DisplayWidget::DisplayWidget(int width, int height, QWidget *parent): QWidget(parent)
{
    //ui.setupUi(this);

    w = width;
    h = height;

    CreateWidgets();
    SetupGui();

    // seed the random number generator
    srand(RAND_SEED);
    GenerateNewData();
}

DisplayWidget::~DisplayWidget()
{
}

void DisplayWidget::CreateWidgets()
{
    bImage = new QImage(w, h, QImage::Format_ARGB32);
    dImage = new QImage(w, h, QImage::Format_ARGB32);
    bimageLabel = new QLabel(this);
    dimageLabel = new QLabel(this);

    debugButton = new QPushButton("DEBUG", this);
    bimageLabel->setStyleSheet("QLabel {background-color: black};");
    dimageLabel->setStyleSheet("QLabel {background-color: white};");

    frameGrab = new QTimer(this);
}

void DisplayWidget::SetupGui()
{
    QHBoxLayout * layout = new QHBoxLayout();
    setLayout(layout); // commenting this line out makes it refresh
    layout->addWidget(bimageLabel);
    layout->addWidget(dimageLabel);
    layout->addWidget(debugButton);

    connect(frameGrab, SIGNAL(timeout()),this, SLOT(GenerateNewData()));
    connect(debugButton, SIGNAL(clicked()), this, SLOT(GenerateNewData()));
    frameGrab->start(50);
}

void DisplayWidget::GenerateNewData()
{
    QRgb * bImageData = (QRgb *)bImage->scanLine(0);
    QRgb * dImageData = (QRgb *)dImage->scanLine(0);

    for (int i; i < w * h; i++)
    {
        bImageData[i] = qRgba(rand() % FULLSCALE, 0, 0, FULLSCALE);
        dImageData[i] = qRgba(0, 0, rand() % FULLSCALE, FULLSCALE);
    }

    bimageLabel->setPixmap(QPixmap::fromImage(*bImage).scaled(QSize(IM_PIXEL_WIDTH, IM_PIXEL_HEIGHT)));
    dimageLabel->setPixmap(QPixmap::fromImage(*dImage).scaled(QSize(IM_PIXEL_WIDTH, IM_PIXEL_HEIGHT)));

    //this->update(); // this breaks it again
}

在这里失去理智。我对Qt 的经验非常有限,但我相信我的方法是正确的。

请帮忙!

【问题讨论】:

  • 我怀疑这与您的布局和尺寸提示有关。详情参考此帖stackoverflow.com/questions/10758267/…
  • 感谢您的回复。我认为我无法准确找出您认为可能存在的问题。当您移动/调整大小/单击小部件上的按钮时,通常会调用哪些函数?更新几何似乎并没有改变任何东西。
  • 我没有给你答案,因为我最近没有使用Qt,但我怀疑再次调用setPixmap后布局的大小没有改变。您可以创建一个派生标签,在更新后返回正确的大小提示。您甚至可以将图像缓存在(派生的)标签中
  • 也许我现在很愚蠢,但我希望在图像大小保持不变的情况下刷新图像像素。 sizehint 什么时候改变?
  • 我已经在 Ubuntu 上测试了代码。我修改了样式以使用灰色和黑色,只是为了更好地查看标签。我已经删除了计时器,以免干扰您的调试按钮。布局按预期工作。它水平布置按钮和标签。是否调用更新没有区别(因为更改标签上的像素图会导致更新)。按下按钮时,图像会更新,大小会按比例缩放,因此按预期保持不变。不确定你期待什么行为......

标签: c++ qt refresh qpixmap qlabel


【解决方案1】:

我已经在 Ubuntu 上测试了您的代码。不幸的是,我不能对 Windows 发表评论。我稍微修改了代码(参见 //@w: 标记的 cmets):

#include "displaywidget.h"

DisplayWidget::DisplayWidget(int width, int height, QWidget *parent): QWidget(parent)
{
    w = width;
    h = height;

    CreateWidgets();
    SetupGui();

    // seed the random number generator
    srand(RAND_SEED);
    GenerateNewData();
}

DisplayWidget::~DisplayWidget()
{
}

void DisplayWidget::CreateWidgets()
{
    bImage = new QImage(w, h, QImage::Format_ARGB32);
    dImage = new QImage(w, h, QImage::Format_ARGB32);

    bimageLabel = new QLabel(this);
    bimageLabel->setScaledContents(true);

    dimageLabel = new QLabel(this);
    dimageLabel->setScaledContents(true);

    debugButton = new QPushButton("DEBUG", this);
    bimageLabel->setStyleSheet("QLabel {background-color: black};");
    dimageLabel->setStyleSheet("QLabel {background-color: grey};");

    frameGrab = new QTimer(this);
}

void DisplayWidget::SetupGui()
{
    //@w: Adding vertical layout as button below seems like better usage of space...
    QVBoxLayout * vlay = new QVBoxLayout();

    QHBoxLayout * hlay = new QHBoxLayout();
    hlay->addWidget(bimageLabel);
    hlay->addWidget(dimageLabel);
    vlay->addLayout(hlay);
    vlay->addWidget(debugButton);

    //@w: Removing size constraints on top layout allows me to resize window and see effect.
    vlay->setSizeConstraint(QLayout::SetNoConstraint);
    setLayout(vlay); // commenting this line out makes it refresh

    connect(frameGrab, SIGNAL(timeout()),this, SLOT(GenerateNewData()));
    //@w: I suppose we can chuck the button.... Currently it serves no purpose
    connect(debugButton, SIGNAL(clicked()), this, SLOT(GenerateNewData()));

    //@w: Timer slower initially, then increase to see where performance degrades.
    frameGrab->start(200);
}

void DisplayWidget::GenerateNewData()
{
    QRgb * bImageData = (QRgb *)bImage->scanLine(0);
    QRgb * dImageData = (QRgb *)dImage->scanLine(0);

    //@w: This code just varies the contents by having a b and d selector that
    //    alternates colour... Simple stuff...
    int bSelect = rand() % 3,
        dSelect = (bSelect==2) ? 0 : bSelect+1;

    for (int i = 0; i < w * h; i++)
    {
        //@w: 3 colours, only two being selected - can be improved, I suppose.
        QRgb rgb[3] =
        {
          (bSelect == 0) || (dSelect==0) ? qRgba(rand() % FULLSCALE, 0, 0, FULLSCALE) : 0,
          (bSelect == 1) || (dSelect==1) ? qRgba(0, rand() % FULLSCALE, 0, FULLSCALE) : 0,
          (bSelect == 2) || (dSelect==2) ? qRgba(0, 0, rand() % FULLSCALE, FULLSCALE) : 0,
        };

        bImageData[i] = rgb[bSelect];
        dImageData[i] = rgb[dSelect];
    }

    //@w: Removed scaling, as it depends on layout...
    bimageLabel->setPixmap(QPixmap::fromImage(*bImage));
    dimageLabel->setPixmap(QPixmap::fromImage(*dImage));
}

最初,标签从像素图中获取其大小。此后,标签遵循布局,遵循表单的大小调整(主/父小部件)

【讨论】:

    【解决方案2】:

    QtForum 为我解决了这个问题,男孩很尴尬。

    我忘了初始化循环计数器。修复一切。

    【讨论】:

      猜你喜欢
      • 2022-01-25
      • 2014-10-13
      • 2011-06-02
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      • 2015-03-30
      • 1970-01-01
      相关资源
      最近更新 更多