繁体   English   中英

QLabel与pixmap图像变得模糊

[英]QLabel with pixmap image getting blurred

我有一张图片,需要显示为QLabel的背景。 这是我的代码(从Qt文档扑杀这里 ):

#include <QtWidgets>    
#include "imageviewer.h"

ImageViewer::ImageViewer()
{
    imageLabel = new QLabel;
    imageLabel->setBackgroundRole(QPalette::Base);
    imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    imageLabel->setScaledContents(true);
    setCentralWidget(imageLabel);

    createActions();
    createMenus();

    resize(570,357);
}


bool ImageViewer::loadFile(const QString &fileName)
{
    QImageReader reader(fileName);
    const QImage image = reader.read();
    if (image.isNull()) {
        QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
                                 tr("Cannot load %1.").arg(QDir::toNativeSeparators(fileName)));
        setWindowFilePath(QString());
        imageLabel->setPixmap(QPixmap());
        imageLabel->adjustSize();
        return false;
    }
    imageLabel->setPixmap(QPixmap::fromImage(image).scaled(size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
    return true;
}



void ImageViewer::open()
{
    QStringList mimeTypeFilters;
    foreach (const QByteArray &mimeTypeName, QImageReader::supportedMimeTypes())
        mimeTypeFilters.append(mimeTypeName);
    mimeTypeFilters.sort();
    const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
    QFileDialog dialog(this, tr("Open File"),
                       picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last());
    dialog.setAcceptMode(QFileDialog::AcceptOpen);
    dialog.setMimeTypeFilters(mimeTypeFilters);
    dialog.selectMimeTypeFilter("image/jpeg");

    while (dialog.exec() == QDialog::Accepted && !loadFile(dialog.selectedFiles().first())) {}
}

void ImageViewer::createActions()
{
    openAct = new QAction(tr("&Open..."), this);
    openAct->setShortcut(tr("Ctrl+O"));
    connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

}

void ImageViewer::createMenus()
{
    fileMenu = new QMenu(tr("&File"), this);
    fileMenu->addAction(openAct);

    menuBar()->addMenu(fileMenu);

}

头文件:

#ifndef IMAGEVIEWER_H
#define IMAGEVIEWER_H

#include <QMainWindow>

class QAction;
class QLabel;
class QMenu;
class QScrollArea;
class QScrollBar;

class ImageViewer : public QMainWindow
{
    Q_OBJECT

public:
    ImageViewer();
    bool loadFile(const QString &);

private slots:
    void open();

private:
    void createActions();
    void createMenus();

    QLabel *imageLabel;
    QAction *openAct;
    QMenu *fileMenu;
};

#endif

主要:

#include <QApplication>
#include <QCommandLineParser>

#include "imageviewer.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QGuiApplication::setApplicationDisplayName(ImageViewer::tr("Image Viewer"));
    ImageViewer imageViewer;
    imageViewer.show();
    return app.exec();
}

如您所见,视口大小是570 x357。我正在使用的图像是这个 (尺寸是2560 x 1600,两者的长宽比均接近1.6,太大而无法在此处上传,因此将上传图片的屏幕截图):

在此处输入图片说明

但是,当我打开应用程序并在其中添加图像时,我在QLabel获得的图像非常模糊:

在此处输入图片说明

如何使标签中的图像与实际图像一样定义(为bmp格式,因此必须在Mac的“文件打开”对话框中将mime类型更改为bmp )?

当我通过QPainter进行此任务时,即从图像文件中制作一个QImage ,然后将其传递给绘画工具并调用update它将很好。 但是我需要能够在单击时内联缩放图像(这是通过在QLabel上调用resize()实现的),并且QPainter方式不允许我缩放图像。

平台-OS X 10.10(Retina显示屏),Qt 5.3.1,32位。

您正在Qt 5.3中的Retina显示屏Mac上的QLabel中遇到一个已知错误: https : //bugreports.qt.io/browse/QTBUG-42503

从您的图像看来,当您使用QLabel时,您只是在获得图像的非视网膜版本,但是如果您在QPainter中手动进行编码,您将获得源QImage的完整分辨率。 如果是这样,那么这确实是由此错误引起的。

您有两种解决方案:

  1. 推出自己的解决方案,不要使用QLabel。 没有理由,如果不使用QLabel(只需使用带有重写的PaintEvent的自定义QWidget类),就无法轻松地“内联缩放图像”。

  2. 升级到已修复此错误的Qt版本。 无论如何,这可能是正确的解决方案,除非最新版本中的任何回归导致应用程序出现问题。 根据错误报告,此问题已在v5.5.0中修复,因此最新的v5.5.1应该可以正常工作。

第一种方法的示例(为简洁起见,我将标题保留在头文件之外,这很简单):

void ImageWidget::setImage(QImage image)
{
    //Set the image and invalidate our cached pixmap
    m_image = image;
    m_cachedPixmap = QPixmap();
    update();
}

void ImageWidget::paintEvent(QPaintEvent *)
{
    if ( !m_image.isNull() )
    {
        QSize scaledSize = size() * devicePixelRatio();
        if (m_cachedPixmap.size() != scaledSize)
        {
            QImage scaledImage = m_image.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
            m_cachedPixmap = QPixmap::fromImage(scaledImage);
            m_cachedPixmap.setDevicePixelRatio(devicePixelRatio());
        }

        QPainter p(this);
        p.drawPixmap(0, 0, m_cachedPixmap);
    }
}

这只是一个非常基本的小部件,仅将QImage绘制为其完整大小,同时尊重了DevicePixelRatio并因此利用了Retina分辨率。 注意:在非视网膜计算机上对此进行了编码,因此我不能保证它可以在Retina上运行,但是我从Qt的Qt 5.5.1修复程序中获得了基本实现。 像QLabel一样,它也缓存Pixmap,因此不必每次调用paintEvent时都重新缩放,除非该窗口小部件实际上已调整大小。

您将图像压缩了4倍以上(2560-> 570),在震荡了这么多之后,似乎图像中的一些小细节无法保留。

实际上,在将图像缩小很多之后,您将获得或多或少的期望。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM