Utils/ImageView/Inc/ImageView.h

127 lines
4.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <QGraphicsView>
#include <QImage>
#include <QPair>
#include <QPixmap>
#include <QString>
#include <QVector>
#include <Qt>
class QLabel;
class QEvent;
class QGestureEvent;
class QGraphicsPixmapItem;
class QGraphicsScene;
class QMouseEvent;
class QPinchGesture;
class QTabBar;
class QWheelEvent;
// 可缩放、可平移的图片显示控件。
//
// 支持两种显示模式:
// 1) 单图模式:setImage()/loadImage() 直接显示一张未命名图片,标题栏不显示;
// 2) 多图模式:setImages()/setNamedImage() 传入 [名字, 图片] 列表,
// 控件顶部用标签页显示名字,下方显示当前选中的图片。
class ImageView : public QGraphicsView
{
Q_OBJECT
public:
// 一组“名字 + 图片”,对应多图模式下的一个标签页。
using NamedImage = QPair<QString, QImage>;
explicit ImageView(QWidget* parent = nullptr);
~ImageView() override;
void setImage(const QImage& image);
void setImage(const QPixmap& pixmap);
bool loadImage(const QString& filePath);
void clearImage();
// 多图模式:整体替换为指定的一组 [名字, 图片]。
// 若原有当前页的名字仍在新列表中,则继续保持该页;否则显示第一张有图的页。
void setImages(const QVector<NamedImage>& images);
// 多图模式:新增或更新一张命名图片,其余图片与当前页保持不变。
void setNamedImage(const QString& name, const QImage& image);
// 退出多图模式,清空所有命名图片。
void clearImages();
bool isMultiImageMode() const;
int imageCount() const;
QString imageName(int index) const;
QImage namedImage(const QString& name) const;
int currentImageIndex() const;
void setCurrentImageIndex(int index);
bool hasImage() const;
QImage image() const;
// 比例以原始图片大小为基准,1.0 表示 100%。
double zoomRatio() const;
void setZoomRatio(double ratio);
void zoomIn(double factor = 1.25);
void zoomOut(double factor = 1.25);
void resetView();
void setZoomRange(double minimum, double maximum);
double minimumZoomRatio() const;
double maximumZoomRatio() const;
// 图片未铺满视口时的停靠方向,默认居中。
void setImageAlignment(Qt::Alignment alignment);
Qt::Alignment imageAlignment() const;
signals:
void imageChanged();
void zoomRatioChanged(double ratio);
// 多图模式下当前标签页发生变化。
void currentImageIndexChanged(int index);
protected:
bool viewportEvent(QEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
private:
bool handleGestureEvent(QGestureEvent* event);
void handlePinchGesture(QPinchGesture* gesture);
void updateZoomLabel();
void updateZoomRatio(double ratio, bool keepCenter);
void updateZoomRatioAt(double ratio, const QPoint& viewportAnchor);
void repositionZoomLabel();
// 显示单张图片;空图片等价于清空当前画面。
void updatePixmap(const QImage& image);
// 清空画面,保留多图列表。
void resetScene();
// 按 m_images 刷新标签页标题与可见性,并调整视口边距。
void refreshTabBar();
// 切换到指定标签页并显示对应图片。
void showImageAt(int index);
QGraphicsScene* m_scene;
QGraphicsPixmapItem* m_pixmapItem;
QLabel* m_zoomLabel;
QTabBar* m_tabBar;
QVector<NamedImage> m_images;
int m_currentImageIndex;
int m_tabBarHeight;
bool m_multiImageMode;
QImage m_image;
double m_zoomRatio;
double m_minimumZoomRatio;
double m_maximumZoomRatio;
Qt::Alignment m_imageAlignment;
bool m_panning;
bool m_pinching;
bool m_needsInitialFit;
double m_pinchStartZoomRatio;
QPoint m_lastMousePosition;
};