feat: add text item with IShape interface decoupling

Extract a pure virtual IShape interface from AbstractShapeType<T> so
  selectors and Document use dynamic_cast<IShape *> instead of
  qgraphicsitem_cast<AbstractShape *>. 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.
This commit is contained in:
jessequ 2026-07-22 09:56:28 +08:00
parent cd343895f9
commit 8ea5033f0d
16 changed files with 484 additions and 26 deletions

View File

@ -65,6 +65,7 @@ set(H_HEADER_FILES
include/graphicsItem/graphicsBaseItem.h include/graphicsItem/graphicsBaseItem.h
include/graphicsItem/graphicsRectItem.h include/graphicsItem/graphicsRectItem.h
include/graphicsItem/graphicsPolygonItem.h include/graphicsItem/graphicsPolygonItem.h
include/graphicsItem/graphicsTextItem.h
include/graphicsItem/graphicsItemGroup.h include/graphicsItem/graphicsItemGroup.h
) )
set(CPP_SOURCE_FILES set(CPP_SOURCE_FILES
@ -93,6 +94,7 @@ set(CPP_SOURCE_FILES
source/graphicsItem/graphicsBaseItem.cpp source/graphicsItem/graphicsBaseItem.cpp
source/graphicsItem/graphicsRectItem.cpp source/graphicsItem/graphicsRectItem.cpp
source/graphicsItem/graphicsPolygonItem.cpp source/graphicsItem/graphicsPolygonItem.cpp
source/graphicsItem/graphicsTextItem.cpp
source/graphicsItem/graphicsItemGroup.cpp source/graphicsItem/graphicsItemGroup.cpp
) )
set(UI_FILES set(UI_FILES

View File

@ -13,7 +13,8 @@ enum GraphicsItemType
GIT_rect = QGraphicsItem::UserType + 3, GIT_rect = QGraphicsItem::UserType + 3,
GIT_roundRect = QGraphicsItem::UserType + 4, GIT_roundRect = QGraphicsItem::UserType + 4,
GIT_ellipse = QGraphicsItem::UserType + 5, GIT_ellipse = QGraphicsItem::UserType + 5,
GIT_polygon = QGraphicsItem::UserType + 6 GIT_polygon = QGraphicsItem::UserType + 6,
GIT_text = QGraphicsItem::UserType + 7
}; };
#endif #endif

View File

@ -17,9 +17,30 @@ enum ShapeType
T_group T_group
}; };
// Common non-template interface for selector dispatch.
// All item types (rect, polygon, text, group) implement this via AbstractShapeType<T>.
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这样不同的基类继承可以共用一些高层的行为定义 //基类采用模板形式QGraphicsItem是默认值,也可以是别的类型比如QGraphicsItemGroup这样不同的基类继承可以共用一些高层的行为定义
template <typename BaseType = QGraphicsItem> template <typename BaseType = QGraphicsItem>
class AbstractShapeType : public BaseType class AbstractShapeType : public BaseType, public IShape
{ {
public: public:
explicit AbstractShapeType(QGraphicsItem *parent = 0) explicit AbstractShapeType(QGraphicsItem *parent = 0)

View File

@ -0,0 +1,72 @@
#ifndef GRAPHICSTEXTITEM_H
#define GRAPHICSTEXTITEM_H
#include "graphicsBaseItem.h"
#include "IPropertyGroupProvider.h"
#include "global.h"
#include <QGraphicsTextItem>
#include <QFont>
class GraphicsTextItem : public AbstractShapeType<QGraphicsTextItem>,
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

View File

@ -14,8 +14,9 @@
enum CreatingMethod enum CreatingMethod
{ {
CM_drag, //多拽,默认的创建方式 CM_drag, // drag-to-create (rect, roundRect)
CM_click //单击点选,如多边形、线段等 CM_click, // click-to-place points (polygon)
CM_place // single click to place (text)
}; };
class GraphicsBaseItem; class GraphicsBaseItem;

View File

@ -107,7 +107,7 @@ bool Document::saveAs(const QString &filePath)
QJsonObject obj; QJsonObject obj;
if (auto *group = dynamic_cast<GraphicsItemGroup *>(item)) if (auto *group = dynamic_cast<GraphicsItemGroup *>(item))
obj = group->serialize(); obj = group->serialize();
else if (auto *shape = qgraphicsitem_cast<AbstractShape *>(item)) else if (auto *shape = dynamic_cast<IShape *>(item))
obj = shape->serialize(); obj = shape->serialize();
if (!obj.isEmpty()) if (!obj.isEmpty())
items.append(obj); items.append(obj);

View File

@ -13,6 +13,8 @@ GraphicElementsPanel::GraphicElementsPanel(QWidget *parent)
connect(ui->pushBtn_roundRect, SIGNAL(clicked()), this, SLOT(onBtnClicked_GraphicsItem())); connect(ui->pushBtn_roundRect, SIGNAL(clicked()), this, SLOT(onBtnClicked_GraphicsItem()));
ui->pushBtn_polygon->setProperty("shap",GIT_polygon); ui->pushBtn_polygon->setProperty("shap",GIT_polygon);
connect(ui->pushBtn_polygon, SIGNAL(clicked()), this, SLOT(onBtnClicked_GraphicsItem())); 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() GraphicElementsPanel::~GraphicElementsPanel()

View File

@ -0,0 +1,319 @@
#include "graphicsItem/graphicsTextItem.h"
#include "graphicsItem/itemControlHandle.h"
#include "graphicsItem/graphicsItemGroup.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QFont>
#include <QGraphicsScene>
#include <QFocusEvent>
#include <QTextDocument>
GraphicsTextItem::GraphicsTextItem(QGraphicsItem *parent)
: AbstractShapeType<QGraphicsTextItem>(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<QString> 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<QGraphicsTextItem>::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<QGraphicsItemGroup *>(parentItem());
if (!group)
setHandleVisible(value.toBool());
else {
setSelected(false);
return QVariant::fromValue<bool>(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;

View File

@ -228,8 +228,10 @@ void CMainWindow::onSignal_selectionChanged()
m_pPropertiesEditorView->setObject(m_pDocument->scene()); m_pPropertiesEditorView->setObject(m_pDocument->scene());
return; return;
} }
GraphicsBaseItem *item = static_cast<GraphicsBaseItem*>(selectedItems.first()); QGraphicsItem *gitem = selectedItems.first();
m_pPropertiesEditorView->setObject(static_cast<QObject*>(item)); QObject *obj = dynamic_cast<QObject *>(gitem);
if (obj)
m_pPropertiesEditorView->setObject(obj);
} }
// -- File operations ------------------------------------------------------- // -- File operations -------------------------------------------------------

View File

@ -2,6 +2,7 @@
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QGraphicsView> #include <QGraphicsView>
#include <graphicsItem/graphicsBaseItem.h> #include <graphicsItem/graphicsBaseItem.h>
#include <graphicsItem/graphicsTextItem.h>
#include <QDebug> #include <QDebug>
QPointF BaseSelector::s_ptMouseDown(0.0, 0.0); QPointF BaseSelector::s_ptMouseDown(0.0, 0.0);
@ -37,7 +38,8 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) //只有一个选中 if (items.count() == 1) //只有一个选中
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first()); QGraphicsItem *gitem = items.first();
IShape *item = dynamic_cast<IShape *>(gitem);
if(item) if(item)
{ {
//需要增加当前是否点击在控制点的判断函数 //需要增加当前是否点击在控制点的判断函数
@ -51,7 +53,7 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen
{ {
m_opMode = OM_rotate; 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 dLengthY = s_ptMouseLast.y() - originPoint.y();
double dLengthX = s_ptMouseLast.x() - originPoint.x(); double dLengthX = s_ptMouseLast.x() - originPoint.x();
s_dAngleMouseDownToItem = atan2(dLengthY, dLengthX) * 180 / M_PI; s_dAngleMouseDownToItem = atan2(dLengthY, dLengthX) * 180 / M_PI;
@ -87,7 +89,8 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen
for(int n = 0; n < items.size(); n++) for(int n = 0; n < items.size(); n++)
{ {
//创建副本 //创建副本
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.at(n)); IShape *item = dynamic_cast<IShape *>(items.at(n));
if (item)
item->createOperationCopy(); item->createOperationCopy();
} }
} }
@ -108,7 +111,8 @@ void BaseSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene
if (items.count() == 1) if (items.count() == 1)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first()); QGraphicsItem *gitem = items.first();
IShape *item = dynamic_cast<IShape *>(gitem);
if(item) if(item)
{ {
if(s_nDragHandle == H_none) if(s_nDragHandle == H_none)
@ -128,7 +132,7 @@ void BaseSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene
else else
{ {
//划分为四组区间范围,分别水平组、垂直组、一三象限倾斜组、二四象限倾斜组,每组由两个对称区间构成 //划分为四组区间范围,分别水平组、垂直组、一三象限倾斜组、二四象限倾斜组,每组由两个对称区间构成
double dRotation = item->rotation(); double dRotation = gitem->rotation();
dRotation += item->getSyncRotationDataFromParent(); dRotation += item->getSyncRotationDataFromParent();
//让角度保持在正负180的区间也就是上下两个半圈这样易于象限判断 //让角度保持在正负180的区间也就是上下两个半圈这样易于象限判断
if (dRotation > 180) if (dRotation > 180)
@ -295,7 +299,12 @@ void BaseSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, DesignerSc
void BaseSelector::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) void BaseSelector::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene)
{ {
Q_UNUSED(event) Q_UNUSED(event)
Q_UNUSED(scene) QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) {
GraphicsTextItem *textItem = dynamic_cast<GraphicsTextItem *>(items.first());
if (textItem && !textItem->isEditing())
textItem->startEditing();
}
} }
void BaseSelector::setCursor(DesignerScene *scene, const QCursor &cursor) void BaseSelector::setCursor(DesignerScene *scene, const QCursor &cursor)

View File

@ -1,6 +1,7 @@
#include "util/creatingSelector.h" #include "util/creatingSelector.h"
#include "graphicsItem/graphicsRectItem.h" #include "graphicsItem/graphicsRectItem.h"
#include "graphicsItem/graphicsPolygonItem.h" #include "graphicsItem/graphicsPolygonItem.h"
#include "graphicsItem/graphicsTextItem.h"
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QGraphicsView> #include <QGraphicsView>
@ -49,6 +50,19 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer
m_pCreatingItem = new GraphicPolygonItem(); m_pCreatingItem = new GraphicPolygonItem();
} }
break; 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: default:
break; break;
} }

View File

@ -24,7 +24,7 @@ void EditingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) if (items.count() == 1)
{ {
GraphicsBaseItem* item = qgraphicsitem_cast<GraphicsBaseItem*>(items.first()); IShape *item = dynamic_cast<IShape *>(items.first());
if(item) if(item)
{ {
if(s_nDragHandle > H_left) if(s_nDragHandle > H_left)
@ -40,7 +40,7 @@ void EditingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designe
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) if (items.count() == 1)
{ {
GraphicsBaseItem* item = qgraphicsitem_cast<GraphicsBaseItem*>(items.first()); IShape *item = dynamic_cast<IShape *>(items.first());
if(item && s_ptMouseLast != s_ptMouseDown) if(item && s_ptMouseLast != s_ptMouseDown)
{ {
item->updateCoordinate(); item->updateCoordinate();

View File

@ -25,7 +25,7 @@ void MovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSce
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
for(int n = 0; n < items.size(); n++) for(int n = 0; n < items.size(); n++)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.at(n)); IShape *item = dynamic_cast<IShape *>(items.at(n));
if(item) if(item)
item->moveOperationCopy(s_ptMouseLast - s_ptMouseDown); item->moveOperationCopy(s_ptMouseLast - s_ptMouseDown);
} }
@ -36,7 +36,7 @@ void MovingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designer
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
for(int n = 0; n < items.size(); n++) for(int n = 0; n < items.size(); n++)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.at(n)); IShape *item = dynamic_cast<IShape *>(items.at(n));
if(item) if(item)
item->removeOperationCopy(); item->removeOperationCopy();
} }

View File

@ -24,18 +24,19 @@ void RotationSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerS
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) if (items.count() == 1)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first()); QGraphicsItem *gitem = items.first();
IShape *item = dynamic_cast<IShape *>(gitem);
if(item) if(item)
{ {
//计算夹角 //计算夹角
QPointF originPoint = item->mapToScene(item->boundingRect().center()); QPointF originPoint = gitem->mapToScene(gitem->boundingRect().center());
double dLengthY = s_ptMouseLast.y() - originPoint.y(); double dLengthY = s_ptMouseLast.y() - originPoint.y();
double dLengthX = s_ptMouseLast.x() - originPoint.x(); double dLengthX = s_ptMouseLast.x() - originPoint.x();
double dAngleMouseToItem = atan2(dLengthY, dLengthX) * 180 / M_PI; double dAngleMouseToItem = atan2(dLengthY, dLengthX) * 180 / M_PI;
// if(atan2(dLengthY, dLengthX) < 0) // if(atan2(dLengthY, dLengthX) < 0)
// dAngleMouseToItem += 360.0; // dAngleMouseToItem += 360.0;
double rotationAngle = item->rotation() + (dAngleMouseToItem - s_dAngleMouseDownToItem); double rotationAngle = gitem->rotation() + (dAngleMouseToItem - s_dAngleMouseDownToItem);
//让角度保持在正负180的区间也就是上下两个半圈这样易于象限判断 //让角度保持在正负180的区间也就是上下两个半圈这样易于象限判断
if (rotationAngle > 180) if (rotationAngle > 180)
rotationAngle -= 360; rotationAngle -= 360;
@ -53,7 +54,7 @@ void RotationSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Design
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
for(int n = 0; n < items.size(); n++) for(int n = 0; n < items.size(); n++)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.at(n)); IShape *item = dynamic_cast<IShape *>(items.at(n));
if(item) if(item)
{ {
item->removeOperationCopy(); item->removeOperationCopy();

View File

@ -25,7 +25,8 @@ void ScalingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) if (items.count() == 1)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first()); QGraphicsItem *gitem = items.first();
IShape *item = dynamic_cast<IShape *>(gitem);
if(item) if(item)
{ {
if(s_nDragHandle != H_none) if(s_nDragHandle != H_none)
@ -40,8 +41,8 @@ void ScalingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc
} }
//计算缩放倍数 //计算缩放倍数
QPointF iniDelta = item->mapFromScene(s_ptMouseDown) - m_scaleBasePoint; QPointF iniDelta = gitem->mapFromScene(s_ptMouseDown) - m_scaleBasePoint;
QPointF lastDelta = item->mapFromScene(s_ptMouseLast) - m_scaleBasePoint; QPointF lastDelta = gitem->mapFromScene(s_ptMouseLast) - m_scaleBasePoint;
double sx = lastDelta.x() / iniDelta.x(); double sx = lastDelta.x() / iniDelta.x();
double sy = lastDelta.y() / iniDelta.y(); double sy = lastDelta.y() / iniDelta.y();
@ -56,7 +57,7 @@ void ScalingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designe
QList<QGraphicsItem *> items = scene->selectedItems(); QList<QGraphicsItem *> items = scene->selectedItems();
if (items.count() == 1) if (items.count() == 1)
{ {
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first()); IShape *item = dynamic_cast<IShape *>(items.first());
if(item && s_ptMouseLast != s_ptMouseDown) if(item && s_ptMouseLast != s_ptMouseDown)
{ {
item->updateCoordinate(); item->updateCoordinate();

View File

@ -65,6 +65,19 @@
<string>多边形</string> <string>多边形</string>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="pushBtn_text">
<property name="geometry">
<rect>
<x>30</x>
<y>260</y>
<width>81</width>
<height>51</height>
</rect>
</property>
<property name="text">
<string>文本</string>
</property>
</widget>
</widget> </widget>
<widget class="QWidget" name="tab_2"> <widget class="QWidget" name="tab_2">
<attribute name="title"> <attribute name="title">