Skip to content

Commit 91c49a2

Browse files
committed
fix: improve DCI icon image positioning and layout
The layout method for DQuickDciIconImage has been completely rewritten to fix positioning issues, particularly on high-DPI displays. Previously, the image was simply centered using anchors, which could cause misalignment. The new implementation calculates precise pixel- aligned positions by considering device pixel ratios and scene transformations. A timer-based scheduling mechanism was added to prevent excessive layout recalculations. Additionally, smooth rendering is now disabled by default during initialization to improve performance, and geometry/parent change handlers ensure proper layout updates. Log: Fixed DCI icon positioning issues on high-DPI displays Influence: 1. Test DCI icon display on monitors with different DPI settings 2. Verify icon centering remains correct when parent item size changes 3. Test icon positioning when moving between windows or screens 4. Verify smooth property is properly initialized to false 5. Test layout updates when icon image dimensions change 6. Verify no performance regression from timer-based layout scheduling fix: 修复 DCI 图标图像定位和布局问题 DQuickDciIconImage 的布局方法已完全重写,以修复定位问题,特别是在高 DPI 显示器上。之前,图像仅使用锚点居中,可能导致错位。新实现通过考虑设备像素 比和场景变换来计算精确的像素对齐位置。添加了基于定时器的调度机制以防止过 多的布局重新计算。此外,初始化期间默认禁用平滑渲染以提高性能,几何/父项 变更处理程序确保正确的布局更新。 Log: 修复高 DPI 显示器上的 DCI 图标定位问题 Influence: 1. 在不同 DPI 设置的显示器上测试 DCI 图标显示 2. 验证父项大小变化时图标居中保持正确 3. 测试在窗口或屏幕间移动时的图标定位 4. 验证 smooth 属性是否正确初始化为 false 5. 测试图标图像尺寸变化时的布局更新 6. 验证基于定时器的布局调度不会导致性能下降
1 parent 7966d82 commit 91c49a2

3 files changed

Lines changed: 73 additions & 3 deletions

File tree

src/private/dquickdciiconimage.cpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <DPlatformTheme>
1010

1111
#include <QUrlQuery>
12+
#include <QQuickWindow>
13+
#include <QPoint>
1214

1315
DQUICK_BEGIN_NAMESPACE
1416
DGUI_USE_NAMESPACE
@@ -189,8 +191,43 @@ DQuickDciIconImagePrivate::DQuickDciIconImagePrivate(DQuickDciIconImage *qq)
189191

190192
void DQuickDciIconImagePrivate::layout()
191193
{
192-
auto dd = QQuickItemPrivate::get(imageItem);
193-
dd->anchors()->setCenterIn(imageItem->parentItem());
194+
Q_Q(DQuickDciIconImage);
195+
if (!q->isComponentComplete())
196+
return;
197+
198+
qreal targetX = (q->width() - imageItem->width()) / 2.0;
199+
qreal targetY = (q->height() - imageItem->height()) / 2.0;
200+
201+
if (!q->parentItem() || !q->window()) {
202+
imageItem->setPosition(QPointF(targetX, targetY));
203+
return;
204+
}
205+
206+
QPointF scenePos = q->mapToScene(QPointF(targetX, targetY));
207+
208+
qreal dpr = q->window()->effectiveDevicePixelRatio();
209+
210+
qreal physicalX = qRound(scenePos.x() * dpr);
211+
qreal physicalY = qRound(scenePos.y() * dpr);
212+
213+
QPointF localPos = q->mapFromScene(QPointF(physicalX / dpr, physicalY / dpr));
214+
215+
imageItem->setPosition(localPos);
216+
}
217+
218+
void DQuickDciIconImagePrivate::scheduleLayout()
219+
{
220+
Q_Q(DQuickDciIconImage);
221+
222+
if (!layoutTimer) {
223+
layoutTimer = new QTimer(q);
224+
layoutTimer->setSingleShot(true);
225+
layoutTimer->setInterval(50);
226+
QObject::connect(layoutTimer, &QTimer::timeout, q, [this]() {
227+
layout();
228+
});
229+
}
230+
layoutTimer->start();
194231
}
195232

196233
void DQuickDciIconImagePrivate::updateImageSourceUrl()
@@ -211,6 +248,8 @@ DQuickDciIconImage::DQuickDciIconImage(QQuickItem *parent)
211248
connect(d->imageItem, &QQuickImage::implicitWidthChanged, this, [this, d]() { setImplicitWidth(d->imageItem->implicitWidth()); });
212249
connect(d->imageItem, &QQuickImage::implicitHeightChanged, this, [this, d]() { setImplicitHeight(d->imageItem->implicitHeight()); });
213250
connect(this, &DQuickDciIconImage::smoothChanged, d->imageItem, &QQuickImage::setSmooth);
251+
connect(d->imageItem, &QQuickItem::widthChanged, this, [d]() { d->scheduleLayout(); });
252+
connect(d->imageItem, &QQuickItem::heightChanged, this, [d]() { d->scheduleLayout(); });
214253
}
215254

216255
DQuickDciIconImage::~DQuickDciIconImage()
@@ -406,7 +445,7 @@ void DQuickDciIconImage::classBegin()
406445
D_D(DQuickDciIconImage);
407446
QQmlEngine::setContextForObject(d->imageItem, QQmlEngine::contextForObject(this));
408447
QQuickItem::classBegin();
409-
d->imageItem->setSmooth(smooth());
448+
setSmooth(false);
410449
}
411450

412451
void DQuickDciIconImage::componentComplete()
@@ -417,6 +456,28 @@ void DQuickDciIconImage::componentComplete()
417456
d->layout();
418457
}
419458

459+
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
460+
void DQuickDciIconImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
461+
{
462+
QQuickItem::geometryChanged(newGeometry, oldGeometry);
463+
d_func()->scheduleLayout();
464+
}
465+
#else
466+
void DQuickDciIconImage::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
467+
{
468+
QQuickItem::geometryChange(newGeometry, oldGeometry);
469+
d_func()->scheduleLayout();
470+
}
471+
#endif
472+
473+
void DQuickDciIconImage::itemChange(ItemChange change, const ItemChangeData &value)
474+
{
475+
QQuickItem::itemChange(change, value);
476+
if (change == ItemParentHasChanged || change == ItemDevicePixelRatioHasChanged || change == ItemSceneChange) {
477+
d_func()->scheduleLayout();
478+
}
479+
}
480+
420481
class DQuickIconAttachedPrivate : public DCORE_NAMESPACE::DObjectPrivate
421482
{
422483
D_DECLARE_PUBLIC(DQuickIconAttached)

src/private/dquickdciiconimage_p.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ class DQuickDciIconImage : public QQuickItem, DCORE_NAMESPACE::DObject
105105
protected:
106106
void classBegin() override;
107107
void componentComplete() override;
108+
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
109+
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
110+
#else
111+
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
112+
#endif
113+
void itemChange(ItemChange change, const ItemChangeData &value) override;
108114
};
109115

110116
class DQuickIconAttachedPrivate;

src/private/dquickdciiconimage_p_p.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <dobject_p.h>
1414
#include <DDciIconPalette>
1515
#include <DDciIconPlayer>
16+
#include <QTimer>
1617

1718
DQUICK_BEGIN_NAMESPACE
1819
class DQuickDciIconImageItemPrivate;
@@ -41,11 +42,13 @@ class DQuickDciIconImagePrivate : public DCORE_NAMESPACE::DObjectPrivate
4142
public:
4243
DQuickDciIconImagePrivate(DQuickDciIconImage *qq);
4344
void layout();
45+
void scheduleLayout();
4446
void updateImageSourceUrl();
4547
void play(DQMLGlobalObject::ControlState mode);
4648

4749
DDciIconPalette palette;
4850
DQuickIconImage *imageItem;
51+
QTimer *layoutTimer = nullptr;
4952
DQMLGlobalObject::ControlState mode = DQMLGlobalObject::NormalState;
5053
DGuiApplicationHelper::ColorType theme = DGuiApplicationHelper::ColorType::LightType;
5154
bool fallbackToQIcon = true;

0 commit comments

Comments
 (0)