Qt官方示例:Image Viewer Example(带滚动条的图片查看器)

本文介绍了一个图片查看器应用,展示了如何构造带有QLabel的QScrollArea,实现图片加载、保存、复制粘贴功能,以及图像缩放和打印。核心功能包括图像适窗、尺寸调整和不同操作方式的控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个示例演示了一个图片查看器。

构造函数:

ImageViewer::ImageViewer(QWidget *parent)
   : QMainWindow(parent), imageLabel(new QLabel)
   , scrollArea(new QScrollArea)
{
    imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    imageLabel->setScaledContents(true);//标签将缩放其内容以填充所有可用空间,当启用并且标签显示像素图时,它将缩放像素图以填充可用空间。

    scrollArea->setBackgroundRole(QPalette::Dark);
    scrollArea->setWidget(imageLabel);
    scrollArea->setWidgetResizable(true);
    setCentralWidget(scrollArea);

    createActions();

    resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);//初始尺寸为屏幕尺寸的60%
}

使用QLabel显示图片,QLabel作为一个滚动区域的中心部件。

载入和显示图片:

bool ImageViewer::loadFile(const QString &fileName)
{
    QImageReader reader(fileName);
    reader.setAutoTransform(true);
    const QImage newImage = reader.read();
    if (newImage.isNull())
    {
        QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
                                 tr("无法载入 %1: %2").arg(QDir::toNativeSeparators(fileName), reader.errorString()));
        return false;
    }

    setImage(newImage);
    setWindowFilePath(fileName);
    return true;
}

void ImageViewer::setImage(const QImage &newImage)
{
    image = newImage;
    if (image.colorSpace().isValid())
        image.convertToColorSpace(QColorSpace::SRgb);
    imageLabel->setPixmap(QPixmap::fromImage(image));

    scaleFactor = 1.0;//缩放因子重置

    printAct->setEnabled(true);
    fitToWindowAct->setEnabled(true);
    fitToWindowAct->setChecked(true);
    fitToWindow();
    updateActions();
}

保存图片:

bool ImageViewer::saveFile(const QString &fileName)
{
    QImageWriter writer(fileName);
    if (!writer.write(image))
    {
        QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
                                 tr("无法写入 %1: %2").arg(QDir::toNativeSeparators(fileName), writer.errorString()));
        return false;
    }
    return true;
}

将图像复制到剪贴板和从剪贴板获取图像显示:

void ImageViewer::copy()
{
#ifndef QT_NO_CLIPBOARD
    QGuiApplication::clipboard()->setImage(image);
#endif // !QT_NO_CLIPBOARD
}

#ifndef QT_NO_CLIPBOARD
static QImage clipboardImage()
{
    if (const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData())
    {
        if (mimeData->hasImage())
        {
            const QImage image = qvariant_cast<QImage>(mimeData->imageData());
            if (!image.isNull())
                return image;
        }
    }
    return QImage();
}
#endif // !QT_NO_CLIPBOARD

void ImageViewer::paste()
{
#ifndef QT_NO_CLIPBOARD
    const QImage newImage = clipboardImage();
    if (newImage.isNull())
    {
        statusBar()->showMessage(tr("剪贴板没有图像数据"));
    }
    else
    {
        setImage(newImage);
        setWindowFilePath(QString());
    }
#endif // !QT_NO_CLIPBOARD
}

设置切换图像是否适应窗口:

void ImageViewer::normalSize()
{
    imageLabel->adjustSize();//根据小部件的内容调整其大小
    scaleFactor = 1.0;
}

void ImageViewer::fitToWindow()
{
    bool fitToWindow = fitToWindowAct->isChecked();//是否设置适合窗口
    scrollArea->setWidgetResizable(fitToWindow);//滚动条区域内的内容自动调整大小
    if (!fitToWindow)
        normalSize();
    updateActions();
}

根据缩放因子缩放图像,实际上是调整QLabel的大小:

void ImageViewer::zoomIn()//放大
{
    scaleImage(1.25);
}

void ImageViewer::zoomOut()//缩小
{
    scaleImage(0.8);
}

void ImageViewer::scaleImage(double factor)
{
    scaleFactor *= factor;
    imageLabel->resize(scaleFactor * imageLabel->pixmap().size());

    adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
    adjustScrollBar(scrollArea->verticalScrollBar(), factor);

    zoomInAct->setEnabled(scaleFactor < 3.0);
    zoomOutAct->setEnabled(scaleFactor > 0.333);
}

//更新滑动条位置
void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
    scrollBar->setValue(int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep()/2)));
}

打印图片:

void ImageViewer::print()
{
    Q_ASSERT(!imageLabel->pixmap(Qt::ReturnByValue).isNull());
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)

    QPrintDialog dialog(&printer, this);

    if (dialog.exec())
    {
        QPainter painter(&printer);
        
        QPixmap pixmap = imageLabel->pixmap(Qt::ReturnByValue);
        QRect rect = painter.viewport();//可绘制的范围 == printer.paperRect(QPrinter::DevicePixel);
        QSize size = pixmap.size();//源图片的大小
        size.scale(rect.size(), Qt::KeepAspectRatio);//缩放到一个可用容纳图片的范围
        
        painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
        painter.setWindow(pixmap.rect());
        painter.drawPixmap(0, 0, pixmap);
    }
#endif
}

图片的尺寸和打印的纸张尺寸可能差别比较大,所以打印前缩放了一下,确保图片范围在纸张范围之内:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值