摘要:class GraphicObject : public QObject, public QGraphicsItem {Q_OBJECTQ_INTERFACES(QGraphicsItem)public:enum ShapeType { Line, Rect,
基于C++ Qt的图形绘制与XML序列化系统技术栈亮点:
class GraphicObject : public QObject, public QGraphicsItem {Q_OBJECTQ_INTERFACES(QGraphicsItem)public:enum ShapeType { Line, Rect, RoundRect, Ellipse };Q_ENUM(ShapeType)// 元对象系统支持动态属性扩展Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor)protected:void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;QRectF boundingRect const override;private:ShapeType m_type;QPolygonF m_points;QColor m_fillColor = Qt::white;QColor m_strokeColor = Qt::black;};关键技术点:
采用分层序列化策略,通过QXmlStreamWriter实现版本化存储:
100,100;200,200优化策略:
在实现自动对齐功能时,采用R树空间索引优化碰撞检测:
class AlignmentEngine {public:void calculateBestFit(const QList& selected) {RTree index;// 构建空间索引for(auto obj : selected) {auto rect = obj->sceneBoundingRect;qreal bounds[4] = {rect.left, rect.top, rect.right, rect.bottom};index.Insert(bounds, bounds, obj);}// 基于索引计算最优对齐路径// ...}};算法亮点:
动态规划求解最小移动代价支持多目标对齐(左/右/居中/等距分布)基于四叉树的空间分割加速计算class MoveCommand : public QUndoCommand {public:MoveCommand(GraphicObject* obj, const QPointF& oldPos) : m_obj(obj), m_oldPos(oldPos), m_newPos(obj->pos) {}void undo override { m_obj->setPos(m_oldPos); }void redo override { m_obj->setPos(m_newPos); }private:GraphicObject* m_obj;QPointF m_oldPos;QPointF m_newPos;};// 在视图交互中记录命令void GraphicView::mouseReleaseEvent(QMouseEvent* event) {if(m_isDragging) {m_undoStack->push(new MoveCommand(selectedObject, startPos));}}通过插件架构支持自定义图形类型:
class GraphicPluginInterface {public:virtual QString pluginName const = 0;virtual QIcon pluginIcon const = 0;virtual GraphicObject* createGraphic const = 0;};Q_DECLARE_INTERFACE(GraphicPluginInterface, "com.vico.graphicplugin/1.0")QDomElement Rectangle::toXml(QDomDocument& doc) const {QDomElement elem = doc.createElement("Shape");elem.setAttribute("type", "Rectangle");QDomElement rectElem = doc.createElement("Geometry");rectElem.setAttribute("x", pos.x);rectElem.setAttribute("y", pos.y);rectElem.setAttribute("width", m_rect.width);rectElem.setAttribute("height", m_rect.height);elem.appendChild(rectElem);return elem;}void Scene::saveIncremental(const QString& path) {QDomDocument doc;QDomElement root = doc.createElement("Delta");foreach(auto change, m_changeLog) {root.appendChild(change->toXml(doc));}appendToFile(path, doc.toString);}void alignLeft(QList shapes) {if(shapes.isEmpty) return;qreal minX = std::numeric_limits::max;foreach(auto shape, shapes) {minX = qMin(minX, shape->scenePos.x);}foreach(auto shape, shapes) {shape->setPos(minX, shape->y);}}来源:信息百宝囊