Skip to content

Commit e8f7d15

Browse files
authored
[216_39] 修复模板阅览弹窗在高缩放比下显示不全的问题 (#3295)
1 parent 835a49e commit e8f7d15

2 files changed

Lines changed: 70 additions & 7 deletions

File tree

devel/216_39.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# 216_39 PDF 预览对话框高分屏尺寸适配
2+
3+
## 如何测试
4+
5+
1. 编译:`xmake b stem`
6+
2. 启动 Mogan,进入启动页 **Template** 页面。
7+
3. 点击任意模板卡片打开预览对话框。
8+
4.**100% 缩放** 下确认:
9+
- 对话框尺寸正常,预览框为正方形,PDF 内容保持 A4 比例居中显示。
10+
5.**200% 缩放**(或更高 DPI)下确认:
11+
- 对话框**不会超出屏幕**,上下左右均完整可见。
12+
- 预览框仍为 1:1 正方形,但尺寸已被限制在屏幕可用范围内,不会撑满整个屏幕。
13+
- 对话框宽度紧紧包裹预览框,左右无大量留白。
14+
6. 在不同分辨率屏幕(如 1080p / 4K)上重复验证,确认对话框始终适配当前屏幕。
15+
16+
## 2026/05/08 实现说明
17+
18+
### What
19+
20+
修复 Windows 高分屏(200% 缩放)下模板预览对话框尺寸过大、预览框超出屏幕导致上下显示不全的问题。通过引入屏幕可用区域检测和尺寸上限约束,使对话框和预览框在不同 DPI 下均保持合理大小。
21+
22+
#### 修改文件
23+
24+
**src/Plugins/Qt/qt_template_page.cpp**
25+
- 新增 `#include <QGuiApplication>` / `#include <QScreen>`
26+
- `showTemplatePreview` 中:
27+
- 获取当前屏幕 `availableGeometry`,对话框最大高度限制为屏幕可用高度的 **90%**
28+
- 预览框 1:1 正方形尺寸由对话框高度上限推导:最高占对话框高度的 **70%**,再与基准尺寸 `PREVIEW_IMAGE_WIDTH` 取较小值。
29+
- 对话框最大宽度收紧为预览框边长 + 左右边距 + 一个间距余量,不再按屏幕宽度的固定比例扩张。
30+
- 预览框仍使用 `setFixedSize`,内部 `QTPdfPreviewWidget` 通过 `KeepAspectRatio` 渲染保持 PDF A4 比例。
31+
32+
### Why
33+
34+
1. **高分屏溢出**:原代码中 `kPreviewDialogMinW × kPreviewDialogMinH`(700×800)经 `DpiUtils::scaled()` 在 200% 缩放下放大为 1400×1600,在 1080p/4K 逻辑分辨率下极易超出屏幕。
35+
2. **预览框无上限**:原预览框固定为 `600×600` 逻辑像素,高分屏下放大为 1200×1200,加上标题、描述、按钮和边距,总高度远超屏幕可用区域。
36+
37+
### How
38+
39+
- 利用 `QScreen::availableGeometry()` 在对话框创建时获取当前屏幕可用区域,将对话框高度硬上限与屏幕绑定。
40+
- 预览框尺寸改为由**对话框高度**主导(而非独立计算),确保垂直方向不会溢出。
41+
- 对话框宽度反向推导:由确定的预览框边长 + `layoutMargin×2` + `layoutSpacing` 得出,实现“紧紧包裹”预览内容的效果,消除两侧无效留白。

src/Plugins/Qt/qt_template_page.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
#include <QEvent>
1313
#include <QFrame>
1414
#include <QGridLayout>
15+
#include <QGuiApplication>
1516
#include <QHBoxLayout>
1617
#include <QLabel>
1718
#include <QMessageBox>
1819
#include <QMouseEvent>
1920
#include <QProgressDialog>
2021
#include <QPushButton>
2122
#include <QResizeEvent>
23+
#include <QScreen>
2224
#include <QScrollArea>
2325
#include <QShowEvent>
2426
#include <QStyle>
@@ -463,10 +465,32 @@ QTTemplatePage::showTemplatePreview (const QString& templateId) {
463465
QDialog* dialog= new QDialog (this);
464466
dialog->setWindowTitle (
465467
qt_translate ("Template Preview - %1").arg (tmpl->name));
466-
dialog->setMinimumSize (DpiUtils::scaled (kPreviewDialogMinW),
467-
DpiUtils::scaled (kPreviewDialogMinH));
468-
dialog->resize (DpiUtils::scaled (kPreviewDialogMinW),
469-
DpiUtils::scaled (kPreviewDialogMinH));
468+
469+
// 根据屏幕可用区域限制对话框尺寸,防止高分屏下溢出
470+
QScreen* screen= this->screen ();
471+
if (!screen) screen= QGuiApplication::primaryScreen ();
472+
QRect availGeo= screen ? screen->availableGeometry () : QRect ();
473+
int maxDlgH = availGeo.height () > 0 ? qRound (availGeo.height () * 0.9)
474+
: DpiUtils::scaled (kPreviewDialogMinH);
475+
476+
// 预览区尺寸由对话框高度上限决定(1:1 正方形)
477+
int basePreviewSize= DpiUtils::scaled (PREVIEW_IMAGE_WIDTH);
478+
int maxPreviewSize = qRound (maxDlgH * 0.7);
479+
int previewSize = qMin (basePreviewSize, maxPreviewSize);
480+
481+
// 对话框最大宽度收紧:仅比预览框宽一点(边距 + 少量余量)
482+
int marginW = DpiUtils::scaled (kPreviewLayoutMargin) * 2;
483+
int spacingW= DpiUtils::scaled (kPreviewLayoutSpacing);
484+
int maxDlgW = previewSize + marginW + spacingW;
485+
if (availGeo.width () > 0) {
486+
maxDlgW= qMin (maxDlgW, qRound (availGeo.width () * 0.9));
487+
}
488+
489+
int minW= qMin (DpiUtils::scaled (kPreviewDialogMinW), maxDlgW);
490+
int minH= qMin (DpiUtils::scaled (kPreviewDialogMinH), maxDlgH);
491+
dialog->setMinimumSize (minW, minH);
492+
dialog->setMaximumSize (maxDlgW, maxDlgH);
493+
dialog->resize (minW, minH);
470494

471495
QVBoxLayout* layout= new QVBoxLayout (dialog);
472496
layout->setSpacing (DpiUtils::scaled (kPreviewLayoutSpacing));
@@ -502,9 +526,7 @@ QTTemplatePage::showTemplatePreview (const QString& templateId) {
502526

503527
// Preview area using reusable PDF preview widget
504528
QTPdfPreviewWidget* previewWidget= new QTPdfPreviewWidget (dialog);
505-
// 设置固定尺寸,确保无内容时也有足够显示区域
506-
previewWidget->setFixedSize (DpiUtils::scaled (PREVIEW_IMAGE_WIDTH),
507-
DpiUtils::scaled (PREVIEW_IMAGE_WIDTH));
529+
previewWidget->setFixedSize (previewSize, previewSize);
508530

509531
// Load PDF preview
510532
if (!tmpl->previewUrl.isEmpty ()) {

0 commit comments

Comments
 (0)