GrabBag/AppUtils/UICommon/Src/DialogImageViewer.cpp
2025-12-27 09:34:02 +08:00

263 lines
8.9 KiB
C++
Raw 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.

#include "DialogImageViewer.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QScrollBar>
#include <QKeyEvent>
#include <QApplication>
#include <QScreen>
DialogImageViewer::DialogImageViewer(QWidget* parent)
: QDialog(parent)
{
setupUI();
}
DialogImageViewer::~DialogImageViewer()
{
}
void DialogImageViewer::setupUI()
{
// 设置窗口属性
setWindowTitle(QString::fromUtf8("图像查看"));
setWindowFlags(Qt::Dialog | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
setStyleSheet("background-color: rgb(25, 26, 28);");
// 获取屏幕大小设置窗口为屏幕的80%
QScreen* screen = QApplication::primaryScreen();
QRect screenGeometry = screen->availableGeometry();
int width = screenGeometry.width() * 0.8;
int height = screenGeometry.height() * 0.8;
resize(width, height);
// 主布局
QVBoxLayout* mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(10, 10, 10, 10);
mainLayout->setSpacing(10);
// 滚动区域
m_scrollArea = new QScrollArea(this);
m_scrollArea->setWidgetResizable(false);
m_scrollArea->setAlignment(Qt::AlignCenter);
m_scrollArea->setStyleSheet(
"QScrollArea { background-color: rgb(38, 40, 47); border: none; }"
"QScrollBar:vertical { background-color: rgb(38, 40, 47); width: 12px; }"
"QScrollBar::handle:vertical { background-color: rgb(80, 82, 88); border-radius: 6px; min-height: 20px; }"
"QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0px; }"
"QScrollBar:horizontal { background-color: rgb(38, 40, 47); height: 12px; }"
"QScrollBar::handle:horizontal { background-color: rgb(80, 82, 88); border-radius: 6px; min-width: 20px; }"
"QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { width: 0px; }"
);
// 图像标签
m_imageLabel = new QLabel(m_scrollArea);
m_imageLabel->setAlignment(Qt::AlignCenter);
m_imageLabel->setStyleSheet("background-color: rgb(38, 40, 47);");
m_imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
m_imageLabel->setScaledContents(false);
m_scrollArea->setWidget(m_imageLabel);
mainLayout->addWidget(m_scrollArea, 1);
// 底部信息栏
QHBoxLayout* bottomLayout = new QHBoxLayout();
bottomLayout->setSpacing(20);
m_infoLabel = new QLabel(this);
m_infoLabel->setStyleSheet("QLabel { color: rgb(180, 180, 180); font-size: 14px; }");
m_infoLabel->setText(QString::fromUtf8("滚轮缩放 | 拖拽平移 | 双击还原 | ESC退出"));
bottomLayout->addWidget(m_infoLabel);
bottomLayout->addStretch();
// 关闭按钮
QPushButton* btnClose = new QPushButton(QString::fromUtf8("关闭"), this);
btnClose->setFixedSize(100, 35);
btnClose->setStyleSheet(
"QPushButton { background-color: rgb(60, 62, 68); color: rgb(221, 225, 233); "
"border: 1px solid rgb(80, 82, 88); border-radius: 5px; font-size: 14px; }"
"QPushButton:hover { background-color: rgb(80, 82, 88); }"
"QPushButton:pressed { background-color: rgb(50, 52, 58); }"
);
connect(btnClose, &QPushButton::clicked, this, &QDialog::close);
bottomLayout->addWidget(btnClose);
mainLayout->addLayout(bottomLayout);
// 设置焦点策略以接收键盘事件
setFocusPolicy(Qt::StrongFocus);
}
void DialogImageViewer::setImage(const QImage& image, const QString& title)
{
m_originalImage = image;
m_scaleFactor = 1.0;
if (!title.isEmpty()) {
setWindowTitle(QString::fromUtf8("图像查看 - %1").arg(title));
}
// 计算初始缩放比例,使图像适应窗口
if (!m_originalImage.isNull()) {
QSize viewSize = m_scrollArea->viewport()->size();
double scaleX = static_cast<double>(viewSize.width() - 20) / m_originalImage.width();
double scaleY = static_cast<double>(viewSize.height() - 20) / m_originalImage.height();
m_scaleFactor = qMin(scaleX, scaleY);
m_scaleFactor = qMax(m_scaleFactor, MIN_SCALE);
m_scaleFactor = qMin(m_scaleFactor, 1.0); // 初始不放大超过100%
}
updateImageDisplay();
}
void DialogImageViewer::updateImageDisplay()
{
if (m_originalImage.isNull()) {
m_imageLabel->setText(QString::fromUtf8("无图像"));
return;
}
// 计算缩放后的尺寸
int newWidth = static_cast<int>(m_originalImage.width() * m_scaleFactor);
int newHeight = static_cast<int>(m_originalImage.height() * m_scaleFactor);
// 缩放图像
QImage scaledImage = m_originalImage.scaled(newWidth, newHeight,
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
m_imageLabel->resize(scaledImage.size());
// 更新信息标签
QString info = QString::fromUtf8("缩放: %1% | 尺寸: %2x%3 | 滚轮缩放 | 拖拽平移 | 双击还原")
.arg(static_cast<int>(m_scaleFactor * 100))
.arg(m_originalImage.width())
.arg(m_originalImage.height());
m_infoLabel->setText(info);
}
void DialogImageViewer::resetZoom()
{
if (m_originalImage.isNull()) return;
// 重置为适应窗口的缩放比例
QSize viewSize = m_scrollArea->viewport()->size();
double scaleX = static_cast<double>(viewSize.width() - 20) / m_originalImage.width();
double scaleY = static_cast<double>(viewSize.height() - 20) / m_originalImage.height();
m_scaleFactor = qMin(scaleX, scaleY);
m_scaleFactor = qMax(m_scaleFactor, MIN_SCALE);
updateImageDisplay();
// 居中显示
m_scrollArea->horizontalScrollBar()->setValue(
(m_imageLabel->width() - m_scrollArea->viewport()->width()) / 2);
m_scrollArea->verticalScrollBar()->setValue(
(m_imageLabel->height() - m_scrollArea->viewport()->height()) / 2);
}
void DialogImageViewer::wheelEvent(QWheelEvent* event)
{
if (m_originalImage.isNull()) return;
// 获取滚轮方向
double delta = event->angleDelta().y() > 0 ? SCALE_STEP : -SCALE_STEP;
// 计算新的缩放比例
double newScale = m_scaleFactor + delta;
newScale = qMax(newScale, MIN_SCALE);
newScale = qMin(newScale, MAX_SCALE);
if (qAbs(newScale - m_scaleFactor) > 0.001) {
// 保存当前滚动位置比例
QScrollBar* hBar = m_scrollArea->horizontalScrollBar();
QScrollBar* vBar = m_scrollArea->verticalScrollBar();
double hRatio = hBar->maximum() > 0 ? static_cast<double>(hBar->value()) / hBar->maximum() : 0.5;
double vRatio = vBar->maximum() > 0 ? static_cast<double>(vBar->value()) / vBar->maximum() : 0.5;
m_scaleFactor = newScale;
updateImageDisplay();
// 恢复滚动位置比例
hBar->setValue(static_cast<int>(hRatio * hBar->maximum()));
vBar->setValue(static_cast<int>(vRatio * vBar->maximum()));
}
event->accept();
}
void DialogImageViewer::mousePressEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton) {
m_dragging = true;
m_lastPos = event->pos();
setCursor(Qt::ClosedHandCursor);
}
QDialog::mousePressEvent(event);
}
void DialogImageViewer::mouseMoveEvent(QMouseEvent* event)
{
if (m_dragging) {
QPoint delta = event->pos() - m_lastPos;
m_lastPos = event->pos();
QScrollBar* hBar = m_scrollArea->horizontalScrollBar();
QScrollBar* vBar = m_scrollArea->verticalScrollBar();
hBar->setValue(hBar->value() - delta.x());
vBar->setValue(vBar->value() - delta.y());
}
QDialog::mouseMoveEvent(event);
}
void DialogImageViewer::mouseReleaseEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton) {
m_dragging = false;
setCursor(Qt::ArrowCursor);
}
QDialog::mouseReleaseEvent(event);
}
void DialogImageViewer::mouseDoubleClickEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton) {
resetZoom();
}
QDialog::mouseDoubleClickEvent(event);
}
void DialogImageViewer::keyPressEvent(QKeyEvent* event)
{
switch (event->key()) {
case Qt::Key_Escape:
close();
break;
case Qt::Key_Plus:
case Qt::Key_Equal:
// 放大
m_scaleFactor = qMin(m_scaleFactor + SCALE_STEP, MAX_SCALE);
updateImageDisplay();
break;
case Qt::Key_Minus:
// 缩小
m_scaleFactor = qMax(m_scaleFactor - SCALE_STEP, MIN_SCALE);
updateImageDisplay();
break;
case Qt::Key_0:
// 原始大小
m_scaleFactor = 1.0;
updateImageDisplay();
break;
case Qt::Key_F:
// 适应窗口
resetZoom();
break;
default:
QDialog::keyPressEvent(event);
}
}