263 lines
8.9 KiB
C++
263 lines
8.9 KiB
C++
#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);
|
||
}
|
||
}
|