这个示例演示了一个图片查看器。
构造函数:
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
}
图片的尺寸和打印的纸张尺寸可能差别比较大,所以打印前缩放了一下,确保图片范围在纸张范围之内: