QPixmap 在 Qt 中加载许多图像

Posted

技术标签:

【中文标题】QPixmap 在 Qt 中加载许多图像【英文标题】:QPixmap load many images in Qt 【发布时间】:2018-09-10 21:27:33 【问题描述】:

我正在尝试从文件夹加载图像并通过单击GUI 上的按钮(类似于 Windows 图像查看器)查看上一个和下一个图像。此文件夹中的图片名称为xxxx_00.jpgxxxx_99.jpg,因此我使用index++index-- 在单击按钮时更改文件名。

我的代码可以很好地显示第一张图片,但是当我单击按钮查看上一张或下一张图片时,它总是显示

QPixmap::scaled: Pixmap 是一个空像素图

并返回一个空图像(第一个图像消失但没有显示新图像)。

这是我的代码:

在 mainwindow.cpp 中

void MainWindow::on_pushButton_4_clicked()   //previous image

    if (index < 1)
    
        index = 99;
        QLabel label;
        label.setText("Go back");
        label.show();
    
    else
    
        index--;
    
    RefreshFilename();
    loadimage();


void MainWindow::on_pushButton_5_clicked()   //next image

    if (index > 98)
    
        index = 0;
        QLabel label;
        label.setText("ALL SET");
        label.show();
    
    else
    
        index = index + 1;
    
    RefreshFilename();
    loadimage();



void MainWindow::loadimage()

   // image.load(filename);
   // im = image.scaled(500,500,Qt::KeepAspectRatio);

    imageObject = new QImage();
    imageObject->load(filename);
    image = QPixmap::fromImage(*imageObject);
    im = image.scaled(400,400,Qt::KeepAspectRatio);
    scene = new QGraphicsScene(this);
    scene->addPixmap(image);
    scene->setSceneRect(image.rect());
    ui->mainimage->setScene(scene);

我花了整整 2 天的时间来调试这个,但仍然不知道。我期待任何建议和支持!

顺便说一句,Refreshfilename 函数工作正常,所以我没有在这里粘贴它。

【问题讨论】:

你有 QLabel * label 类的成员,然后在构造函数中初始化它: label = new QLabel;然后重用标签:label->setPixmap();标签-> 显示();。请记住,函数完成时会删除局部变量。你不觉得你声明的 QLabels 是本地的吗? 是的,但我没有使用 Qlabel 来显示图像。单击按钮时,我仅使用 QLabel 打印一些注释。我使用 imageObject、image、scene 等来显示图像,这些变量都是 Mainwindow 类中的公共成员。 同样的事情可以做,只需将label->setPixmap(...)改为label->setText(...) 是的,但我使用 *scene 显示图像的原因是我希望图像显示在主窗口上,如果我使用标签,它会显示在新窗口中。是不是因为主窗口无法重新加载场景? 你说的场景我没有看到,如果你需要帮助你应该提供一个minimal reproducible example,你能做到吗? 【参考方案1】:

原因

由于我不知道RefreshFilename(); 做了什么,所以我不能确切地知道原因是什么。

但是,我发现您的代码中有一个重大缺陷,即每次调用 MainWindow::loadimage 时都会创建一个新场景,这会导致内存泄漏。

当你提供更多细节时,我会在这里更具体。

解决方案

设置一次场景并添加一个QGraphicsPixmapItem,然后在loadImage 中更新该项目的像素图。 将当前编号保留在类属性中。

再次,一旦添加详细信息,我将更加具体。

示例

无论如何(等你提供MVCE),我已经根据你的任务描述准备了一个工作示例:

#define IMAGE_COUNT 99

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    m_imgNum(0),
    m_item(new QGraphicsPixmapItem())

    auto *widget = new QWidget(this);
    auto *layoutMain = new QVBoxLayout(widget);
    auto *layoutButtons = new QHBoxLayout();
    auto *btnPrev = new QPushButton(tr("Previous"), this);
    auto *btnNext = new QPushButton(tr("Next"), this);
    auto *view = new QGraphicsView(this);

    view->setScene(new QGraphicsScene(this));
    view->scene()->addItem(m_item);

    layoutButtons->addStretch();
    layoutButtons->addWidget(btnPrev);
    layoutButtons->addWidget(btnNext);
    layoutButtons->addStretch();

    layoutMain->addWidget(view);
    layoutMain->addLayout(layoutButtons);

    setCentralWidget(widget);
    resize(640, 480);
    loadImage();

    connect(btnPrev, &QPushButton::clicked, [this]()
        if (m_imgNum > 0)
            m_imgNum--;
        else
            m_imgNum = IMAGE_COUNT;

        loadImage();
    );

    connect(btnNext, &QPushButton::clicked, [this]()
        if (m_imgNum < IMAGE_COUNT)
            m_imgNum++;
        else
            m_imgNum = 0;

        loadImage();
    );


void MainWindow::loadImage()

    m_item->setPixmap(QString("images/image_%1.jpg").arg(m_imgNum, 2, 10, QChar('0')));

其中m_imgNumm_itemloadImage 在标头中声明为:

private:
    inline void loadImage();

    int m_imgNum;
    QGraphicsPixmapItem *m_item;

【讨论】:

以上是关于QPixmap 在 Qt 中加载许多图像的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt GUI 中加载和显示图像

无法在 Qt5/cmake 项目中加载 Qt 资源文件中指定的图像

如何在文件夹opencv&&qt c++中加载图像[关闭]

在vector<Mat> Opencv中加载许多图像

使用 QQuickImageProvider 在 QML WebEngineView 中加载图像

QT对话框打开图像并用QPixmap显示