From 8ea5033f0dc7f7ee8d150de4bde726f8a6bed717 Mon Sep 17 00:00:00 2001 From: jessequ Date: Wed, 22 Jul 2026 09:56:28 +0800 Subject: [PATCH] feat: add text item with IShape interface decoupling Extract a pure virtual IShape interface from AbstractShapeType so selectors and Document use dynamic_cast instead of qgraphicsitem_cast. This decouples the selector system from the template hierarchy, enabling GraphicsTextItem (backed by QGraphicsTextItem) to work uniformly with all existing selectors. GraphicsTextItem supports inline text editing (double-click to edit, focus-out to finish), font/color properties via PropertyEditor, resize with proportional font scaling, move, rotate, and full serialization. Adds CM_place creation mode for single-click placement. --- CMakeLists.txt | 2 + include/global.h | 3 +- include/graphicsItem/graphicsBaseItem.h | 23 +- include/graphicsItem/graphicsTextItem.h | 72 +++++ include/util/creatingSelector.h | 5 +- source/document.cpp | 2 +- source/graphicElementsPanel.cpp | 2 + source/graphicsItem/graphicsTextItem.cpp | 319 +++++++++++++++++++++++ source/mainwindow.cpp | 6 +- source/util/baseSelector.cpp | 23 +- source/util/creatingSelector.cpp | 14 + source/util/editingSelector.cpp | 4 +- source/util/movingSelector.cpp | 4 +- source/util/rotationSelector.cpp | 9 +- source/util/scalingSelector.cpp | 9 +- ui/graphicElementsPanel.ui | 13 + 16 files changed, 484 insertions(+), 26 deletions(-) create mode 100644 include/graphicsItem/graphicsTextItem.h create mode 100644 source/graphicsItem/graphicsTextItem.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 079344c..aad0154 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ set(H_HEADER_FILES include/graphicsItem/graphicsBaseItem.h include/graphicsItem/graphicsRectItem.h include/graphicsItem/graphicsPolygonItem.h + include/graphicsItem/graphicsTextItem.h include/graphicsItem/graphicsItemGroup.h ) set(CPP_SOURCE_FILES @@ -93,6 +94,7 @@ set(CPP_SOURCE_FILES source/graphicsItem/graphicsBaseItem.cpp source/graphicsItem/graphicsRectItem.cpp source/graphicsItem/graphicsPolygonItem.cpp + source/graphicsItem/graphicsTextItem.cpp source/graphicsItem/graphicsItemGroup.cpp ) set(UI_FILES diff --git a/include/global.h b/include/global.h index 41eee44..a644f67 100644 --- a/include/global.h +++ b/include/global.h @@ -13,7 +13,8 @@ enum GraphicsItemType GIT_rect = QGraphicsItem::UserType + 3, GIT_roundRect = QGraphicsItem::UserType + 4, GIT_ellipse = QGraphicsItem::UserType + 5, - GIT_polygon = QGraphicsItem::UserType + 6 + GIT_polygon = QGraphicsItem::UserType + 6, + GIT_text = QGraphicsItem::UserType + 7 }; #endif diff --git a/include/graphicsItem/graphicsBaseItem.h b/include/graphicsItem/graphicsBaseItem.h index 178d63e..d486487 100644 --- a/include/graphicsItem/graphicsBaseItem.h +++ b/include/graphicsItem/graphicsBaseItem.h @@ -17,9 +17,30 @@ enum ShapeType T_group }; +// Common non-template interface for selector dispatch. +// All item types (rect, polygon, text, group) implement this via AbstractShapeType. +class IShape +{ +public: + virtual ~IShape() {} + virtual int collidesWithHandle(const QPointF &point) = 0; + virtual void createOperationCopy() = 0; + virtual void removeOperationCopy() = 0; + virtual void moveOperationCopy(const QPointF &) = 0; + virtual void rotateOperationCopy(const double &) = 0; + virtual void syncRotationDataFromParent(const double &) = 0; + virtual double getSyncRotationDataFromParent() = 0; + virtual QPointF getSymmetricPointPos(int nHandle) = 0; + virtual void resize(int, double, double, const QPointF &) = 0; + virtual void updateCoordinate() = 0; + virtual void editShape(int, const QPointF &) = 0; + virtual void move(const QPointF &) = 0; + virtual QJsonObject serialize() const = 0; +}; + //基类采用模板形式,QGraphicsItem是默认值,也可以是别的类型,比如QGraphicsItemGroup,这样不同的基类继承可以共用一些高层的行为定义 template -class AbstractShapeType : public BaseType +class AbstractShapeType : public BaseType, public IShape { public: explicit AbstractShapeType(QGraphicsItem *parent = 0) diff --git a/include/graphicsItem/graphicsTextItem.h b/include/graphicsItem/graphicsTextItem.h new file mode 100644 index 0000000..284f344 --- /dev/null +++ b/include/graphicsItem/graphicsTextItem.h @@ -0,0 +1,72 @@ +#ifndef GRAPHICSTEXTITEM_H +#define GRAPHICSTEXTITEM_H + +#include "graphicsBaseItem.h" +#include "IPropertyGroupProvider.h" +#include "global.h" + +#include +#include + +class GraphicsTextItem : public AbstractShapeType, + public IPropertyGroupProvider +{ + Q_OBJECT + Q_PROPERTY(QString text READ toPlainText WRITE setPlainText) + Q_PROPERTY(QFont itemFont READ itemFont WRITE setItemFont) + Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) + Q_PROPERTY(QColor backgroundColor READ brushColor WRITE setBrushColor) + +public: + explicit GraphicsTextItem(QGraphicsItem *parent = nullptr); + virtual ~GraphicsTextItem(); + + // IPropertyGroupProvider + QString getPropertyGroup(const QString &propertyName) const override; + + // Override QGraphicsItem::type() + enum { Type = GIT_text }; + int type() const override { return Type; } + + void resize(int nHandle, double dSX, double dSY, const QPointF &basePoint) override; + void updateCoordinate() override; + void move(const QPointF &pt) override; + QJsonObject serialize() const override; + static QGraphicsItem *createFromJson(const QJsonObject &obj); + + void createOperationCopy() override; + void removeOperationCopy() override; + void moveOperationCopy(const QPointF &) override; + void rotateOperationCopy(const double &) override; + void syncRotationDataFromParent(const double &) override; + + // Font property accessors + QFont itemFont() const { return font(); } + void setItemFont(const QFont &f) { setFont(f); updateSizeFromText(); } + + // Text color accessor (foreground) + QColor textColor() const { return defaultTextColor(); } + void setTextColor(const QColor &c) { setDefaultTextColor(c); } + + // Editing mode (separate from selection) + void startEditing(); + void endEditing(); + bool isEditing() const { return m_bEditing; } + +protected: + QPainterPath shape() override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + void focusOutEvent(QFocusEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + +private: + void updateHandles() override; + void updateSizeFromText(); + + QRectF m_lastBoundingRect; + double m_dLastPointSize = 14; + bool m_bEditing = false; +}; + +#endif // GRAPHICSTEXTITEM_H diff --git a/include/util/creatingSelector.h b/include/util/creatingSelector.h index 4e0ba6a..b843e50 100644 --- a/include/util/creatingSelector.h +++ b/include/util/creatingSelector.h @@ -14,8 +14,9 @@ enum CreatingMethod { - CM_drag, //多拽,默认的创建方式 - CM_click //单击点选,如多边形、线段等 + CM_drag, // drag-to-create (rect, roundRect) + CM_click, // click-to-place points (polygon) + CM_place // single click to place (text) }; class GraphicsBaseItem; diff --git a/source/document.cpp b/source/document.cpp index 14054b7..ef1f10c 100644 --- a/source/document.cpp +++ b/source/document.cpp @@ -107,7 +107,7 @@ bool Document::saveAs(const QString &filePath) QJsonObject obj; if (auto *group = dynamic_cast(item)) obj = group->serialize(); - else if (auto *shape = qgraphicsitem_cast(item)) + else if (auto *shape = dynamic_cast(item)) obj = shape->serialize(); if (!obj.isEmpty()) items.append(obj); diff --git a/source/graphicElementsPanel.cpp b/source/graphicElementsPanel.cpp index 2213ca5..351705c 100644 --- a/source/graphicElementsPanel.cpp +++ b/source/graphicElementsPanel.cpp @@ -13,6 +13,8 @@ GraphicElementsPanel::GraphicElementsPanel(QWidget *parent) connect(ui->pushBtn_roundRect, SIGNAL(clicked()), this, SLOT(onBtnClicked_GraphicsItem())); ui->pushBtn_polygon->setProperty("shap",GIT_polygon); connect(ui->pushBtn_polygon, SIGNAL(clicked()), this, SLOT(onBtnClicked_GraphicsItem())); + ui->pushBtn_text->setProperty("shap",GIT_text); + connect(ui->pushBtn_text, SIGNAL(clicked()), this, SLOT(onBtnClicked_GraphicsItem())); } GraphicElementsPanel::~GraphicElementsPanel() diff --git a/source/graphicsItem/graphicsTextItem.cpp b/source/graphicsItem/graphicsTextItem.cpp new file mode 100644 index 0000000..3b70d64 --- /dev/null +++ b/source/graphicsItem/graphicsTextItem.cpp @@ -0,0 +1,319 @@ +#include "graphicsItem/graphicsTextItem.h" +#include "graphicsItem/itemControlHandle.h" +#include "graphicsItem/graphicsItemGroup.h" + +#include +#include +#include +#include +#include +#include + +GraphicsTextItem::GraphicsTextItem(QGraphicsItem *parent) + : AbstractShapeType(parent) +{ + m_type = T_item; + m_pen = QPen(Qt::NoPen); + m_brush = QBrush(Qt::NoBrush); + + // 8 resize handles + m_vecHanle.reserve(H_left); + for (int i = H_leftTop; i <= H_left; i++) { + auto *h = new ItemControlHandle(this); + h->setType(T_resize); + h->setTag(i); + m_vecHanle.push_back(h); + } + // 4 rotate handles + for (int i = H_rotate_leftTop; i <= H_rotate_leftBottom; i++) { + auto *h = new ItemControlHandle(this); + h->setType(T_rotate); + h->setTag(i); + m_vecHanle.push_back(h); + } + + setFlag(QGraphicsItem::ItemIsMovable, false); // we handle move via selector + setFlag(QGraphicsItem::ItemIsSelectable, true); + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + setAcceptHoverEvents(true); + + QFont defaultFont; + defaultFont.setPointSize(14); + setFont(defaultFont); + setDefaultTextColor(Qt::black); + setPlainText("Text"); + + updateSizeFromText(); + m_boundingRect = QRectF(0, 0, m_dWidth, m_dHeight); + setTransformOriginPoint(m_boundingRect.center()); + m_lastBoundingRect = m_boundingRect; + + // Keep bounding rect in sync with text content during editing + connect(document(), &QTextDocument::contentsChanged, this, [this]() { + prepareGeometryChange(); + updateSizeFromText(); + m_boundingRect = QRectF(0, 0, m_dWidth, m_dHeight); + setTransformOriginPoint(m_boundingRect.center()); + updateHandles(); + m_lastBoundingRect = m_boundingRect; + }); +} + +GraphicsTextItem::~GraphicsTextItem() {} + +QString GraphicsTextItem::getPropertyGroup(const QString &propertyName) const +{ + QList properties = { + QStringLiteral("text"), + QStringLiteral("itemFont"), + QStringLiteral("textColor"), + QStringLiteral("backgroundColor") + }; + + if (!properties.contains(propertyName)) + return {}; + else + return QStringLiteral("基本信息"); +} + +QPainterPath GraphicsTextItem::shape() +{ + QPainterPath path; + path.addRect(m_boundingRect); + return path; +} + +void GraphicsTextItem::updateSizeFromText() +{ + QSizeF textSize = document()->size(); + double w = qMax(textSize.width(), 40.0); + double h = qMax(textSize.height(), 20.0); + m_dWidth = w; + m_dHeight = h; +} + +void GraphicsTextItem::updateCoordinate() +{ + if (!parentItem()) { + updateSizeFromText(); + prepareGeometryChange(); + m_boundingRect = QRectF(0, 0, m_dWidth, m_dHeight); + setTransformOriginPoint(m_boundingRect.center()); + updateHandles(); + } + m_lastBoundingRect = m_boundingRect; + m_dLastPointSize = font().pointSize(); +} + +void GraphicsTextItem::updateHandles() +{ + AbstractShapeType::updateHandles(); +} + +void GraphicsTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + // Background fill + if (m_brush.style() != Qt::NoBrush) { + painter->setPen(Qt::NoPen); + painter->setBrush(m_brush); + painter->drawRect(m_boundingRect); + } + + // Text rendering via QGraphicsTextItem + QGraphicsTextItem::paint(painter, option, widget); + + // Selection indicator + if (option->state & QStyle::State_Selected) { + int nPenWidth = 1; + painter->setPen(QPen(QColor(70, 70, 70), nPenWidth, Qt::DashLine)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(m_boundingRect_selected); + + painter->setBrush(Qt::red); + painter->drawEllipse(transformOriginPoint(), 4, 4); + } +} + +void GraphicsTextItem::resize(int nHandle, double dSX, double dSY, const QPointF &basePoint) +{ + switch (nHandle) { + case H_left: + case H_right: + dSY = 1; + break; + case H_top: + case H_bottom: + dSX = 1; + break; + default: + break; + } + + QTransform trans; + trans.translate(basePoint.x(), basePoint.y()); + trans.scale(dSX, dSY); + trans.translate(-basePoint.x(), -basePoint.y()); + + prepareGeometryChange(); + m_boundingRect = trans.mapRect(m_lastBoundingRect); + m_dWidth = m_boundingRect.width(); + m_dHeight = m_boundingRect.height(); + + // Scale font size proportionally from pre-drag value + double avgScale = (qAbs(dSX) + qAbs(dSY)) / 2.0; + QFont f = font(); + int newSize = qMax(1, qRound(m_dLastPointSize * avgScale)); + f.setPointSize(newSize); + setFont(f); + + setTransformOriginPoint(m_boundingRect.center()); + updateHandles(); +} + +void GraphicsTextItem::move(const QPointF &pt) +{ + moveBy(pt.x(), pt.y()); +} + +QVariant GraphicsTextItem::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == QGraphicsItem::ItemSelectedHasChanged) { + QGraphicsItemGroup *group = dynamic_cast(parentItem()); + if (!group) + setHandleVisible(value.toBool()); + else { + setSelected(false); + return QVariant::fromValue(false); + } + } + return QGraphicsTextItem::itemChange(change, value); +} + +void GraphicsTextItem::startEditing() +{ + m_bEditing = true; + setHandleVisible(false); + setTextInteractionFlags(Qt::TextEditorInteraction); + setFocus(); +} + +void GraphicsTextItem::endEditing() +{ + m_bEditing = false; + setTextInteractionFlags(Qt::NoTextInteraction); + updateCoordinate(); + if (isSelected()) + setHandleVisible(true); +} + +void GraphicsTextItem::focusOutEvent(QFocusEvent *event) +{ + QGraphicsTextItem::focusOutEvent(event); + endEditing(); +} + +void GraphicsTextItem::focusInEvent(QFocusEvent *event) +{ + QGraphicsTextItem::focusInEvent(event); + setHandleVisible(false); +} + +void GraphicsTextItem::createOperationCopy() +{ + m_pOperationCopy = new QGraphicsPathItem(shape()); + m_pOperationCopy->setPen(Qt::DashLine); + m_pOperationCopy->setPos(pos()); + m_pOperationCopy->setTransformOriginPoint(transformOriginPoint()); + m_pOperationCopy->setTransform(transform()); + m_pOperationCopy->setRotation(rotation()); + m_pOperationCopy->setScale(scale()); + m_pOperationCopy->setZValue(zValue()); + + QGraphicsScene *s = scene(); + if (s && m_pOperationCopy) { + s->addItem(m_pOperationCopy); + m_movingIniPos = pos(); + } +} + +void GraphicsTextItem::removeOperationCopy() +{ + QGraphicsScene *s = scene(); + if (s && m_pOperationCopy) { + if (pos() != m_pOperationCopy->pos()) + setPos(m_pOperationCopy->pos()); + if (rotation() != m_pOperationCopy->rotation()) + setRotation(m_pOperationCopy->rotation()); + s->removeItem(m_pOperationCopy); + delete m_pOperationCopy; + m_pOperationCopy = nullptr; + } +} + +void GraphicsTextItem::moveOperationCopy(const QPointF &distance) +{ + if (m_pOperationCopy) + m_pOperationCopy->setPos(m_movingIniPos + distance); +} + +void GraphicsTextItem::rotateOperationCopy(const double &dAngle) +{ + if (m_pOperationCopy) + m_pOperationCopy->setRotation(dAngle); +} + +void GraphicsTextItem::syncRotationDataFromParent(const double &data) +{ + m_dSyncRotationByParent += data; + if (m_dSyncRotationByParent > 180) + m_dSyncRotationByParent -= 360; + if (m_dSyncRotationByParent < -180) + m_dSyncRotationByParent += 360; +} + +#include "util/serializationUtils.h" + +QJsonObject GraphicsTextItem::serialize() const +{ + QJsonObject obj = serializeCommon(this, "text"); + obj["text"] = toPlainText(); + QJsonObject fontObj; + fontObj["family"] = font().family(); + fontObj["bold"] = font().bold(); + fontObj["italic"] = font().italic(); + fontObj["underline"] = font().underline(); + fontObj["pointSize"] = font().pointSize(); + obj["font"] = fontObj; + obj["textColor"] = defaultTextColor().name(QColor::HexArgb); + obj["backgroundColor"] = m_brush.color().name(QColor::HexArgb); + return obj; +} + +#include "util/serializationRegistry.h" + +QGraphicsItem *GraphicsTextItem::createFromJson(const QJsonObject &obj) +{ + auto *item = new GraphicsTextItem(); + item->setPlainText(obj["text"].toString()); + QJsonObject f = obj["font"].toObject(); + QFont font(f["family"].toString(), f["pointSize"].toInt(14)); + font.setBold(f["bold"].toBool()); + font.setItalic(f["italic"].toBool()); + font.setUnderline(f["underline"].toBool()); + item->setFont(font); + item->setDefaultTextColor(QColor(obj["textColor"].toString())); + QColor bgColor(obj["backgroundColor"].toString()); + if (bgColor.isValid()) + item->setBrushColor(bgColor); + applyCommon(item, obj); + item->updateSizeFromText(); + item->updateCoordinate(); + item->setHandleVisible(false); + return item; +} + +static struct TextItemRegistrar { + TextItemRegistrar() { + registerItemFactory("text", &GraphicsTextItem::createFromJson); + } +} _textItemRegistrar; diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 9069fdf..f5e3894 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -228,8 +228,10 @@ void CMainWindow::onSignal_selectionChanged() m_pPropertiesEditorView->setObject(m_pDocument->scene()); return; } - GraphicsBaseItem *item = static_cast(selectedItems.first()); - m_pPropertiesEditorView->setObject(static_cast(item)); + QGraphicsItem *gitem = selectedItems.first(); + QObject *obj = dynamic_cast(gitem); + if (obj) + m_pPropertiesEditorView->setObject(obj); } // -- File operations ------------------------------------------------------- diff --git a/source/util/baseSelector.cpp b/source/util/baseSelector.cpp index 80a5379..7cd1b93 100644 --- a/source/util/baseSelector.cpp +++ b/source/util/baseSelector.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include QPointF BaseSelector::s_ptMouseDown(0.0, 0.0); @@ -37,7 +38,8 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen QList items = scene->selectedItems(); if (items.count() == 1) //只有一个选中 { - AbstractShape* item = qgraphicsitem_cast(items.first()); + QGraphicsItem *gitem = items.first(); + IShape *item = dynamic_cast(gitem); if(item) { //需要增加当前是否点击在控制点的判断函数 @@ -51,7 +53,7 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen { m_opMode = OM_rotate; //计算夹角 - QPointF originPoint = item->mapToScene(item->boundingRect().center()); + QPointF originPoint = gitem->mapToScene(gitem->boundingRect().center()); double dLengthY = s_ptMouseLast.y() - originPoint.y(); double dLengthX = s_ptMouseLast.x() - originPoint.x(); s_dAngleMouseDownToItem = atan2(dLengthY, dLengthX) * 180 / M_PI; @@ -87,8 +89,9 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen for(int n = 0; n < items.size(); n++) { //创建副本 - AbstractShape* item = qgraphicsitem_cast(items.at(n)); - item->createOperationCopy(); + IShape *item = dynamic_cast(items.at(n)); + if (item) + item->createOperationCopy(); } } else if(m_opMode == OM_none) @@ -108,7 +111,8 @@ void BaseSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene if (items.count() == 1) { - AbstractShape* item = qgraphicsitem_cast(items.first()); + QGraphicsItem *gitem = items.first(); + IShape *item = dynamic_cast(gitem); if(item) { if(s_nDragHandle == H_none) @@ -128,7 +132,7 @@ void BaseSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene else { //划分为四组区间范围,分别水平组、垂直组、一三象限倾斜组、二四象限倾斜组,每组由两个对称区间构成 - double dRotation = item->rotation(); + double dRotation = gitem->rotation(); dRotation += item->getSyncRotationDataFromParent(); //让角度保持在正负180的区间,也就是上下两个半圈,这样易于象限判断 if (dRotation > 180) @@ -295,7 +299,12 @@ void BaseSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, DesignerSc void BaseSelector::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) { Q_UNUSED(event) - Q_UNUSED(scene) + QList items = scene->selectedItems(); + if (items.count() == 1) { + GraphicsTextItem *textItem = dynamic_cast(items.first()); + if (textItem && !textItem->isEditing()) + textItem->startEditing(); + } } void BaseSelector::setCursor(DesignerScene *scene, const QCursor &cursor) diff --git a/source/util/creatingSelector.cpp b/source/util/creatingSelector.cpp index 5e9ed75..76a1548 100644 --- a/source/util/creatingSelector.cpp +++ b/source/util/creatingSelector.cpp @@ -1,6 +1,7 @@ #include "util/creatingSelector.h" #include "graphicsItem/graphicsRectItem.h" #include "graphicsItem/graphicsPolygonItem.h" +#include "graphicsItem/graphicsTextItem.h" #include #include @@ -49,6 +50,19 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer m_pCreatingItem = new GraphicPolygonItem(); } break; + case GIT_text: + { + GraphicsTextItem *textItem = new GraphicsTextItem(); + textItem->setPos(event->scenePos()); + textItem->updateCoordinate(); + textItem->setSelected(true); + scene->addItem(textItem); + emit scene->signalAddItem(textItem); + + setCursor(scene, Qt::ArrowCursor); + emit setWorkingSelector(ST_base); + } + break; default: break; } diff --git a/source/util/editingSelector.cpp b/source/util/editingSelector.cpp index 7e6b401..8c65aec 100644 --- a/source/util/editingSelector.cpp +++ b/source/util/editingSelector.cpp @@ -24,7 +24,7 @@ void EditingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc QList items = scene->selectedItems(); if (items.count() == 1) { - GraphicsBaseItem* item = qgraphicsitem_cast(items.first()); + IShape *item = dynamic_cast(items.first()); if(item) { if(s_nDragHandle > H_left) @@ -40,7 +40,7 @@ void EditingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designe QList items = scene->selectedItems(); if (items.count() == 1) { - GraphicsBaseItem* item = qgraphicsitem_cast(items.first()); + IShape *item = dynamic_cast(items.first()); if(item && s_ptMouseLast != s_ptMouseDown) { item->updateCoordinate(); diff --git a/source/util/movingSelector.cpp b/source/util/movingSelector.cpp index 17988a3..fded3cc 100644 --- a/source/util/movingSelector.cpp +++ b/source/util/movingSelector.cpp @@ -25,7 +25,7 @@ void MovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSce QList items = scene->selectedItems(); for(int n = 0; n < items.size(); n++) { - AbstractShape* item = qgraphicsitem_cast(items.at(n)); + IShape *item = dynamic_cast(items.at(n)); if(item) item->moveOperationCopy(s_ptMouseLast - s_ptMouseDown); } @@ -36,7 +36,7 @@ void MovingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designer QList items = scene->selectedItems(); for(int n = 0; n < items.size(); n++) { - AbstractShape* item = qgraphicsitem_cast(items.at(n)); + IShape *item = dynamic_cast(items.at(n)); if(item) item->removeOperationCopy(); } diff --git a/source/util/rotationSelector.cpp b/source/util/rotationSelector.cpp index 1c0dce1..698c1ed 100644 --- a/source/util/rotationSelector.cpp +++ b/source/util/rotationSelector.cpp @@ -24,18 +24,19 @@ void RotationSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerS QList items = scene->selectedItems(); if (items.count() == 1) { - AbstractShape* item = qgraphicsitem_cast(items.first()); + QGraphicsItem *gitem = items.first(); + IShape *item = dynamic_cast(gitem); if(item) { //计算夹角 - QPointF originPoint = item->mapToScene(item->boundingRect().center()); + QPointF originPoint = gitem->mapToScene(gitem->boundingRect().center()); double dLengthY = s_ptMouseLast.y() - originPoint.y(); double dLengthX = s_ptMouseLast.x() - originPoint.x(); double dAngleMouseToItem = atan2(dLengthY, dLengthX) * 180 / M_PI; // if(atan2(dLengthY, dLengthX) < 0) // dAngleMouseToItem += 360.0; - double rotationAngle = item->rotation() + (dAngleMouseToItem - s_dAngleMouseDownToItem); + double rotationAngle = gitem->rotation() + (dAngleMouseToItem - s_dAngleMouseDownToItem); //让角度保持在正负180的区间,也就是上下两个半圈,这样易于象限判断 if (rotationAngle > 180) rotationAngle -= 360; @@ -53,7 +54,7 @@ void RotationSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Design QList items = scene->selectedItems(); for(int n = 0; n < items.size(); n++) { - AbstractShape* item = qgraphicsitem_cast(items.at(n)); + IShape *item = dynamic_cast(items.at(n)); if(item) { item->removeOperationCopy(); diff --git a/source/util/scalingSelector.cpp b/source/util/scalingSelector.cpp index 9ac7cad..ac90dcd 100644 --- a/source/util/scalingSelector.cpp +++ b/source/util/scalingSelector.cpp @@ -25,7 +25,8 @@ void ScalingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc QList items = scene->selectedItems(); if (items.count() == 1) { - AbstractShape* item = qgraphicsitem_cast(items.first()); + QGraphicsItem *gitem = items.first(); + IShape *item = dynamic_cast(gitem); if(item) { if(s_nDragHandle != H_none) @@ -40,8 +41,8 @@ void ScalingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc } //计算缩放倍数 - QPointF iniDelta = item->mapFromScene(s_ptMouseDown) - m_scaleBasePoint; - QPointF lastDelta = item->mapFromScene(s_ptMouseLast) - m_scaleBasePoint; + QPointF iniDelta = gitem->mapFromScene(s_ptMouseDown) - m_scaleBasePoint; + QPointF lastDelta = gitem->mapFromScene(s_ptMouseLast) - m_scaleBasePoint; double sx = lastDelta.x() / iniDelta.x(); double sy = lastDelta.y() / iniDelta.y(); @@ -56,7 +57,7 @@ void ScalingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designe QList items = scene->selectedItems(); if (items.count() == 1) { - AbstractShape* item = qgraphicsitem_cast(items.first()); + IShape *item = dynamic_cast(items.first()); if(item && s_ptMouseLast != s_ptMouseDown) { item->updateCoordinate(); diff --git a/ui/graphicElementsPanel.ui b/ui/graphicElementsPanel.ui index d18d984..9d16630 100644 --- a/ui/graphicElementsPanel.ui +++ b/ui/graphicElementsPanel.ui @@ -65,6 +65,19 @@ 多边形 + + + + 30 + 260 + 81 + 51 + + + + 文本 + +