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:
parent
cd343895f9
commit
8ea5033f0d
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<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,这样不同的基类继承可以共用一些高层的行为定义
|
||||
template <typename BaseType = QGraphicsItem>
|
||||
class AbstractShapeType : public BaseType
|
||||
class AbstractShapeType : public BaseType, public IShape
|
||||
{
|
||||
public:
|
||||
explicit AbstractShapeType(QGraphicsItem *parent = 0)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ bool Document::saveAs(const QString &filePath)
|
|||
QJsonObject obj;
|
||||
if (auto *group = dynamic_cast<GraphicsItemGroup *>(item))
|
||||
obj = group->serialize();
|
||||
else if (auto *shape = qgraphicsitem_cast<AbstractShape *>(item))
|
||||
else if (auto *shape = dynamic_cast<IShape *>(item))
|
||||
obj = shape->serialize();
|
||||
if (!obj.isEmpty())
|
||||
items.append(obj);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -228,8 +228,10 @@ void CMainWindow::onSignal_selectionChanged()
|
|||
m_pPropertiesEditorView->setObject(m_pDocument->scene());
|
||||
return;
|
||||
}
|
||||
GraphicsBaseItem *item = static_cast<GraphicsBaseItem*>(selectedItems.first());
|
||||
m_pPropertiesEditorView->setObject(static_cast<QObject*>(item));
|
||||
QGraphicsItem *gitem = selectedItems.first();
|
||||
QObject *obj = dynamic_cast<QObject *>(gitem);
|
||||
if (obj)
|
||||
m_pPropertiesEditorView->setObject(obj);
|
||||
}
|
||||
|
||||
// -- File operations -------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <graphicsItem/graphicsBaseItem.h>
|
||||
#include <graphicsItem/graphicsTextItem.h>
|
||||
#include <QDebug>
|
||||
|
||||
QPointF BaseSelector::s_ptMouseDown(0.0, 0.0);
|
||||
|
|
@ -37,7 +38,8 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
if (items.count() == 1) //只有一个选中
|
||||
{
|
||||
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first());
|
||||
QGraphicsItem *gitem = items.first();
|
||||
IShape *item = dynamic_cast<IShape *>(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<AbstractShape*>(items.at(n));
|
||||
item->createOperationCopy();
|
||||
IShape *item = dynamic_cast<IShape *>(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<AbstractShape*>(items.first());
|
||||
QGraphicsItem *gitem = items.first();
|
||||
IShape *item = dynamic_cast<IShape *>(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<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)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "util/creatingSelector.h"
|
||||
#include "graphicsItem/graphicsRectItem.h"
|
||||
#include "graphicsItem/graphicsPolygonItem.h"
|
||||
#include "graphicsItem/graphicsTextItem.h"
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsView>
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ void EditingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
if (items.count() == 1)
|
||||
{
|
||||
GraphicsBaseItem* item = qgraphicsitem_cast<GraphicsBaseItem*>(items.first());
|
||||
IShape *item = dynamic_cast<IShape *>(items.first());
|
||||
if(item)
|
||||
{
|
||||
if(s_nDragHandle > H_left)
|
||||
|
|
@ -40,7 +40,7 @@ void EditingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designe
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
if (items.count() == 1)
|
||||
{
|
||||
GraphicsBaseItem* item = qgraphicsitem_cast<GraphicsBaseItem*>(items.first());
|
||||
IShape *item = dynamic_cast<IShape *>(items.first());
|
||||
if(item && s_ptMouseLast != s_ptMouseDown)
|
||||
{
|
||||
item->updateCoordinate();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ void MovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSce
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
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->moveOperationCopy(s_ptMouseLast - s_ptMouseDown);
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ void MovingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designer
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
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->removeOperationCopy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,18 +24,19 @@ void RotationSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerS
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
if (items.count() == 1)
|
||||
{
|
||||
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first());
|
||||
QGraphicsItem *gitem = items.first();
|
||||
IShape *item = dynamic_cast<IShape *>(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<QGraphicsItem *> items = scene->selectedItems();
|
||||
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->removeOperationCopy();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ void ScalingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerSc
|
|||
QList<QGraphicsItem *> items = scene->selectedItems();
|
||||
if (items.count() == 1)
|
||||
{
|
||||
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first());
|
||||
QGraphicsItem *gitem = items.first();
|
||||
IShape *item = dynamic_cast<IShape *>(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<QGraphicsItem *> items = scene->selectedItems();
|
||||
if (items.count() == 1)
|
||||
{
|
||||
AbstractShape* item = qgraphicsitem_cast<AbstractShape*>(items.first());
|
||||
IShape *item = dynamic_cast<IShape *>(items.first());
|
||||
if(item && s_ptMouseLast != s_ptMouseDown)
|
||||
{
|
||||
item->updateCoordinate();
|
||||
|
|
|
|||
|
|
@ -65,6 +65,19 @@
|
|||
<string>多边形</string>
|
||||
</property>
|
||||
</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 class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
|
|
|
|||
Loading…
Reference in New Issue