
Qt/CPP 编写的多平台图形编辑器。 其主要目标是以简单直观的方式对二维图形进行可视化编辑。 纯Qt开发不涉及第三方库。 特点 轻松创建小型至中型图形1000 节点/边并进行参数化。 节点和边的常见视觉属性形状、大小、颜色、标签等。 有向图、无向图和混合图。 直边和多边形边节点端口。 图表及其元素的自定义用户定义属性。 动态维护节点之间的交换列表。 在图形元素及其属性中搜索。 通过 GraphViz 引擎自动布局图表dot、neato、fdp、sfdp、circo。 将图表导出到PDF、SVG、各种图像格式BMP、PNG、JPG、TIFF 等。 支持的图形文件格式XGR本机图形持久化格式、GEXF公共子集的读/写簇和动态属性除外、GraphML读/写、GML通过OGDF读取通过QVGE写入、GraphViz DOT通过 GraphViz/boost/OGDF 读取通过 QVGE 写入 源码 使用Qt5.13.1_MinGW编译通过。最近在图形编辑领域折腾用Qt/CPP写了个多平台图形编辑器感觉还挺有意思来和大家分享分享。一、目标与实现路径这个图形编辑器的主要目标就是以一种简单直观的方式对二维图形进行可视化编辑。而且为了保证它的纯净性和可移植性我选择了纯Qt开发不引入任何第三方库。这就像是一场自我挑战在Qt提供的“工具箱”里打造出满足各种图形编辑需求的“利器”。二、功能特点剖析1. 创建与参数化图形这个编辑器可以轻松创建小型至中型图形能处理1000 节点/边呢。就像下面这段代码是创建节点的简单示例// 创建一个节点 Node* createNode(QPointF position) { Node* node new Node(); node-setPos(position); // 设置节点的一些默认属性 node-setShape(Node::Rectangle); node-setColor(Qt::red); node-setSize(QSizeF(50, 50)); return node; }这里通过Node类的实例化设置其位置、形状、颜色和大小等属性完成一个节点的创建。节点和边都有常见的视觉属性比如形状、大小、颜色、标签等这些属性的设置为图形的多样化呈现提供了基础。2. 支持多种图类型无论是有向图、无向图还是混合图这个编辑器都能轻松应对。比如在表示边的时候我们可以通过一个简单的标识来区分有向和无向class Edge { public: bool isDirected; // 其他边的属性和方法 };通过isDirected这个布尔变量就能清晰地区分边的方向特性进而支持不同类型图的构建。3. 多样化的边与节点端口编辑器支持直边和多边形边以及节点端口。在实现多边形边的时候可以利用Qt的图形绘制功能像这样void PolygonEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); QPainterPath path; // 添加多边形的各个点到路径 foreach(const QPointF point, polygonPoints) { if (path.isEmpty()) { path.moveTo(point); } else { path.lineTo(point); } } painter-drawPath(path); }这里通过QPainterPath来构建多边形的路径然后用painter绘制出来。4. 自定义属性图表及其元素支持自定义用户定义属性。我们可以通过一个属性映射表来实现class GraphElement { public: QMapQString, QVariant customProperties; // 设置自定义属性的方法 void setCustomProperty(const QString key, const QVariant value) { customProperties[key] value; } // 获取自定义属性的方法 QVariant getCustomProperty(const QString key) const { return customProperties.value(key); } };这样用户就可以根据自己的需求为图形元素添加各种自定义属性。5. 动态维护交换列表动态维护节点之间的交换列表这在实际应用中很重要比如在进行图形的布局调整等操作时。实现这个功能可以通过一个QList来存储交换信息QListNodeSwapInfo nodeSwapList; struct NodeSwapInfo { Node* node1; Node* node2; // 交换时间等其他相关信息 };每当有节点交换操作时就往这个列表里添加相应的信息。6. 搜索功能在图形元素及其属性中搜索也是编辑器的一个亮点。我们可以通过遍历图形元素对其属性进行匹配搜索示例代码如下QListGraphElement* searchElements(const QString searchText) { QListGraphElement* resultList; foreach(GraphElement* element, allGraphElements) { if (element-getCustomProperty(label).toString().contains(searchText) || element-getCustomProperty(description).toString().contains(searchText)) { resultList.append(element); } } return resultList; }这里通过遍历所有图形元素检查其特定自定义属性中是否包含搜索文本从而找到符合条件的元素。7. 自动布局与导出通过GraphViz引擎实现自动布局图表支持dot、neato、fdp、sfdp、circo等布局方式。导出功能也很强大可以将图表导出到PDF、SVG以及各种图像格式BMP、PNG、JPG、TIFF等。例如导出为PDF的代码片段QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(graph.pdf); QPainter painter(printer); scene-render(painter); painter.end();这里利用QPrinter和QPainter实现了将图形场景渲染并输出为PDF文件。8. 文件格式支持支持多种图形文件格式像XGR本机图形持久化格式、GEXF公共子集的读/写簇和动态属性除外、GraphML读/写、GML通过OGDF读取通过QVGE写入、GraphViz DOT通过GraphViz/boost/OGDF读取通过QVGE写入。不同格式的读写操作涉及到对文件结构的解析和生成是个比较复杂但也很有趣的过程。三、源码编译这个项目使用Qt5.13.1_MinGW编译通过。在编译过程中需要注意Qt版本的兼容性以及相关依赖库的配置。确保环境搭建正确才能顺利将代码编译成可用的图形编辑器。Qt/CPP 编写的多平台图形编辑器。 其主要目标是以简单直观的方式对二维图形进行可视化编辑。 纯Qt开发不涉及第三方库。 特点 轻松创建小型至中型图形1000 节点/边并进行参数化。 节点和边的常见视觉属性形状、大小、颜色、标签等。 有向图、无向图和混合图。 直边和多边形边节点端口。 图表及其元素的自定义用户定义属性。 动态维护节点之间的交换列表。 在图形元素及其属性中搜索。 通过 GraphViz 引擎自动布局图表dot、neato、fdp、sfdp、circo。 将图表导出到PDF、SVG、各种图像格式BMP、PNG、JPG、TIFF 等。 支持的图形文件格式XGR本机图形持久化格式、GEXF公共子集的读/写簇和动态属性除外、GraphML读/写、GML通过OGDF读取通过QVGE写入、GraphViz DOT通过 GraphViz/boost/OGDF 读取通过 QVGE 写入 源码 使用Qt5.13.1_MinGW编译通过。总的来说用Qt/CPP打造这个多平台图形编辑器是一次充满挑战与收获的旅程。从功能的构思到代码的实现每一步都凝聚着对图形编辑技术的探索和追求。希望这篇博文能给对图形编辑开发感兴趣的小伙伴们一些启发。