GrabBag/AppUtils/UICommon/Src/DialogImageViewer.cpp

263 lines
8.9 KiB
C++
Raw Normal View History

2025-12-27 09:34:02 +08:00
#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);
}
}