Skip to content

Commit a44ed03

Browse files
committed
[重构图形绘制组件并修复线条定位问题]: 对GraphicsPixmapItem进行模块化重构,修复SectionalSubtitlesView中线条定位计算错误,提升代码质量和用户体验
-**重构GraphicsPixmapItem**: 将掩码绘制功能拆分为CursorManager和MaskPainter辅助类,改进代码结构和可维护性 -**修复SectionalSubtitlesView线条定位**: 使用场景实际边界计算线条位置,确保线条不会超出边界范围 -**统一头文件保护**: 将#ifndef宏定义改为#pragma once指令,简化头文件管理 -**优化信号参数类型**: 将itemSelected信号参数从QGraphicsItem*改为具体GraphicsTextItem*类型,提高类型安全性 -**重命名GeometryCache接口**: setControlPoints改为setGeometryData,boundingRect/shape改为visualBoundingRect/visualShape,更准确反映功能 -**改进掩码编辑模式**: 将Mode枚举改为MaskEditingMode,相关方法重命名为setMaskEditingMode/setBrushSize等,语义更清晰 -**修复视图缩放因子更新**: 在paint事件中动态更新光标缩放比例,确保光标显示正确 -**清理资源管理**: 使用QScopedPointer管理私有实现,确保资源正确释放 -**调整线条边距**: 将SubtitleDividerLineItem的边距从0.5调整为1,改善视觉效果
1 parent 0f19af7 commit a44ed03

21 files changed

Lines changed: 378 additions & 205 deletions

examples/graphics/drawscene.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#ifndef DRAWSCENE_HPP
2-
#define DRAWSCENE_HPP
1+
#pragma once
32

43
#include <QGraphicsScene>
54

@@ -18,7 +17,7 @@ class DrawScene : public QGraphicsScene
1817

1918
signals:
2019
void deleteItem();
21-
void itemSelected(QGraphicsItem *item);
20+
void itemSelected(Graphics::GraphicsTextItem *item);
2221

2322
private slots:
2423
void editorLostFocus(Graphics::GraphicsTextItem *item);
@@ -31,5 +30,3 @@ private slots:
3130
bool m_drawText = false;
3231
QColor m_textColor;
3332
};
34-
35-
#endif // DRAWSCENE_HPP

examples/graphics/drawwidget.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,9 @@ void DrawWidget::textColorChanged()
191191
textButtonTriggered();
192192
}
193193

194-
void DrawWidget::itemSelected(QGraphicsItem *item)
194+
void DrawWidget::itemSelected(Graphics::GraphicsTextItem *item)
195195
{
196-
auto textItem = qgraphicsitem_cast<GraphicsTextItem *>(item);
196+
auto *textItem = qgraphicsitem_cast<GraphicsTextItem *>(item);
197197
if (!textItem) {
198198
return;
199199
}

examples/graphics/drawwidget.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ class QToolBar;
66
class QListWidgetItem;
77
class QGraphicsItem;
88

9+
namespace Graphics {
10+
class GraphicsTextItem;
11+
}
12+
913
class DrawWidget : public QWidget
1014
{
1115
Q_OBJECT
@@ -21,7 +25,7 @@ private slots:
2125
void handleFontChange();
2226
void textButtonTriggered();
2327
void textColorChanged();
24-
void itemSelected(QGraphicsItem *item);
28+
void itemSelected(Graphics::GraphicsTextItem *item);
2529

2630
private:
2731
void setupUI();

examples/graphics/maskdialog.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ void MaskDialog::onButtonClicked(int id)
8888
if (!pixmapItem) {
8989
return;
9090
}
91-
GraphicsPixmapItem::Mode mode = GraphicsPixmapItem::Normal;
91+
auto mode = GraphicsPixmapItem::MaskEditingMode::Normal;
9292
switch (id) {
93-
case 1: mode = GraphicsPixmapItem::MaskDraw; break;
94-
case 2: mode = GraphicsPixmapItem::MaskErase; break;
95-
case 3: pixmapItem->clearMask(); break;
93+
case 1: mode = GraphicsPixmapItem::MaskEditingMode::Draw; break;
94+
case 2: mode = GraphicsPixmapItem::MaskEditingMode::Erase; break;
95+
case 3: pixmapItem->resetMask(); break;
9696
default: break;
9797
}
98-
pixmapItem->setPaintMode(mode);
98+
pixmapItem->setMaskEditingMode(mode);
9999
}
100100

101101
void MaskDialog::onPenSizeChanged(int value)
@@ -104,7 +104,7 @@ void MaskDialog::onPenSizeChanged(int value)
104104
if (!pixmapItem) {
105105
return;
106106
}
107-
pixmapItem->setPenSize(value);
107+
pixmapItem->setBrushSize(value);
108108
}
109109

110110
void MaskDialog::onOpacityChanged(double value)
@@ -113,7 +113,7 @@ void MaskDialog::onOpacityChanged(double value)
113113
if (!pixmapItem) {
114114
return;
115115
}
116-
pixmapItem->setOpacity(value);
116+
pixmapItem->setMaskOpacity(value);
117117
}
118118

119119
void MaskDialog::onSave()

examples/graphics/sectionalsubtitlesview.cc

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,35 @@ SectionalSubtitlesView::~SectionalSubtitlesView() {}
2929

3030
void SectionalSubtitlesView::setImageAfter()
3131
{
32-
auto rect = sceneRect();
33-
auto y = rect.height() / 5.0 * 4;
34-
scene()->addItem(d_ptr->line1Ptr.data());
35-
scene()->addItem(d_ptr->line2Ptr.data());
36-
d_ptr->line1Ptr->setLine(QLineF(1, y, rect.width() - 1, y));
37-
d_ptr->line2Ptr->setLine(QLineF(1, rect.height() - 1, rect.width() - 1, rect.height() - 1));
32+
scene()->addItem(d_ptr->line1Ptr.get());
33+
scene()->addItem(d_ptr->line2Ptr.get());
34+
35+
const auto sceneRect = this->sceneRect();
36+
37+
// 使用 sceneRect 的实际边界,而不是假设左上角为 (0,0)
38+
const auto left = sceneRect.left();
39+
const auto right = sceneRect.right();
40+
const auto top = sceneRect.top();
41+
const auto bottom = sceneRect.bottom();
42+
const auto width = sceneRect.width();
43+
const auto height = sceneRect.height();
44+
45+
// 计算线的位置
46+
const auto topLineY = top + height * 0.8; // 从实际顶部开始计算的4/5位置
47+
48+
// 计算边距,确保线条不会超出边界
49+
const auto margin = std::max({d_ptr->line1Ptr->margin(), d_ptr->line2Ptr->margin(), 1.0}) / 2.0;
50+
const auto x1 = left + margin; // 左侧位置(考虑实际左边界)
51+
const auto x2 = right - margin; // 右侧位置(考虑实际右边界)
52+
const auto y2 = bottom - margin; // 底部位置(考虑实际底部边界)
53+
54+
// 创建水平线
55+
QLineF topLine(x1, topLineY, x2, topLineY);
56+
QLineF bottomLine(x1, y2, x2, y2);
57+
58+
// 设置线条
59+
d_ptr->line1Ptr->setLine(topLine);
60+
d_ptr->line2Ptr->setLine(bottomLine);
3861
}
3962

4063
auto SectionalSubtitlesView::clipImage() const -> QImage
@@ -64,7 +87,7 @@ auto SectionalSubtitlesView::info() const -> StitchingImageInfo
6487

6588
auto SectionalSubtitlesView::line1RatioOfHeight() const -> double
6689
{
67-
return (static_cast<int>(d_ptr->line1Ptr->line().y1()) * 1.0 / pixmap().size().height());
90+
return d_ptr->line1Ptr->line().y1() / sceneRect().height();
6891
}
6992

7093
void SectionalSubtitlesView::setLine1RatioOfHeight(double value)
@@ -76,7 +99,7 @@ void SectionalSubtitlesView::setLine1RatioOfHeight(double value)
7699

77100
auto SectionalSubtitlesView::line2RatioOfHeight() const -> double
78101
{
79-
return (static_cast<int>(d_ptr->line2Ptr->line().y1()) * 1.0 / pixmap().size().height());
102+
return d_ptr->line2Ptr->line().y1() / sceneRect().height();
80103
}
81104

82105
void SectionalSubtitlesView::setLine2RatioOfHeight(double value)

examples/graphics/subtitledividerlineitem.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
SubtitleDividerLineItem::SubtitleDividerLineItem(QGraphicsItem *parent)
66
: GraphicsLineItem(parent)
77
{
8-
setMargin(0.5);
8+
setMargin(1);
99
setShowBoundingRect(false);
1010
setShowShape(false);
1111
}

src/graphics/geometrycache.hpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ class GeometryCache
1313
GeometryCache() = default;
1414
~GeometryCache() = default;
1515

16-
void setControlPoints(const QPolygonF &points) { setControlPoints(points, {}, {}); }
16+
void setControlPoints(const QPolygonF &points) { setGeometryData(points, {}, {}); }
1717

18-
void setControlPoints(const QPolygonF &points, const QRectF &bounds, const QPainterPath &path)
18+
void setGeometryData(const QPolygonF &points, const QRectF &bounds, const QPainterPath &path)
1919
{
2020
if (m_controlPoints == points && m_bounds == bounds && m_basePath == path) {
2121
return;
@@ -29,25 +29,24 @@ class GeometryCache
2929

3030
QPolygonF controlPoints() const { return m_controlPoints; }
3131

32-
QRectF boundingRect(double margin, double penWidth, double expandAmount)
32+
QRectF visualBoundingRect(double margin, double penWidth, double expandAmount)
3333
{
34-
updateCachedData(margin, penWidth, expandAmount);
34+
updateCacheIfNeeded(margin, penWidth, expandAmount);
3535
return m_cachedBounds;
3636
}
3737

38-
QPainterPath shape(double margin, double penWidth, double expandAmount)
38+
QPainterPath visualShape(double margin, double penWidth, double expandAmount)
3939
{
40-
updateCachedData(margin, penWidth, expandAmount);
40+
updateCacheIfNeeded(margin, penWidth, expandAmount);
4141
return m_cachedPath;
4242
}
4343

44-
bool isValid() const { return !m_bounds.isNull() && !m_controlPoints.isEmpty(); }
45-
void invalidate() { m_bounds = QRectF(); }
44+
bool hasValidGeometry() const { return !m_bounds.isNull() && !m_controlPoints.isEmpty(); }
4645

4746
private:
48-
void updateCachedData(double margin, double penWidth, double expandAmount)
47+
void updateCacheIfNeeded(double margin, double penWidth, double expandAmount)
4948
{
50-
const double expansion = computeExpansion(margin, penWidth, expandAmount);
49+
const double expansion = calculateTotalExpansion(margin, penWidth, expandAmount);
5150
if (!m_cacheDirty && qFuzzyCompare(m_cachedExpansion, expansion)) {
5251
return; // 缓存仍然有效
5352
}
@@ -59,7 +58,7 @@ class GeometryCache
5958
m_cachedBounds = m_cachedPath.controlPointRect();
6059
}
6160

62-
static double computeExpansion(double margin, double penWidth, double expandAmount)
61+
static double calculateTotalExpansion(double margin, double penWidth, double expandAmount)
6362
{
6463
return std::max({margin * 0.5, penWidth, expandAmount});
6564
}
@@ -71,8 +70,7 @@ class GeometryCache
7170
bool m_cacheDirty = true; // 路径是否需要重新计算
7271
double m_cachedExpansion = 0; // 路径扩展长度
7372
QPainterPath m_cachedPath; // 缓存路径
74-
75-
QRectF m_cachedBounds; // 缓存矩形
73+
QRectF m_cachedBounds; // 缓存矩形
7674
};
7775

7876
using GeometryCachePtr = QScopedPointer<GeometryCache>;

src/graphics/graphicsarcitem.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ auto GraphicsArcItem::setArc(const Arc &arc) -> bool
136136

137137
prepareGeometryChange();
138138
d_ptr->arch = arc;
139-
geometryCache()->setControlPoints(anchorPoints,
140-
Utils::createBoundingRect(pts, 0),
141-
d_ptr->arcPath);
139+
geometryCache()->setGeometryData(anchorPoints,
140+
Utils::createBoundingRect(pts, 0),
141+
d_ptr->arcPath);
142142

143143
return true;
144144
}

src/graphics/graphicsbasicitem.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,22 @@ GraphicsBasicItem::~GraphicsBasicItem() {}
5252

5353
auto GraphicsBasicItem::isValid() const -> bool
5454
{
55-
return d_ptr->geometryCachePtr->isValid();
55+
return d_ptr->geometryCachePtr->hasValidGeometry();
5656
}
5757

5858
auto GraphicsBasicItem::boundingRect() const -> QRectF
5959
{
60-
return d_ptr->geometryCachePtr->isValid()
61-
? d_ptr->geometryCachePtr->boundingRect(margin(), pen().width(), d_ptr->minExpandSize)
60+
return d_ptr->geometryCachePtr->hasValidGeometry()
61+
? d_ptr->geometryCachePtr->visualBoundingRect(margin(),
62+
pen().width(),
63+
d_ptr->minExpandSize)
6264
: scene()->sceneRect();
6365
}
6466

6567
auto GraphicsBasicItem::shape() const -> QPainterPath
6668
{
67-
return d_ptr->geometryCachePtr->isValid()
68-
? d_ptr->geometryCachePtr->shape(margin(), pen().width(), d_ptr->minExpandSize)
69+
return d_ptr->geometryCachePtr->hasValidGeometry()
70+
? d_ptr->geometryCachePtr->visualShape(margin(), pen().width(), d_ptr->minExpandSize)
6971
: QAbstractGraphicsShapeItem::shape();
7072
}
7173

src/graphics/graphicscircleitem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ auto GraphicsCircleItem::setCircle(const Circle &circle) -> bool
7676

7777
prepareGeometryChange();
7878
d_ptr->circle = circle;
79-
geometryCache()->setControlPoints(d_ptr->circle.controlPoints(), rect, shape);
79+
geometryCache()->setGeometryData(d_ptr->circle.controlPoints(), rect, shape);
8080

8181
return true;
8282
}

0 commit comments

Comments
 (0)