您现在的位置是:首页 >其他 >流程图拖拽视觉编程-流程编辑器2网站首页其他
流程图拖拽视觉编程-流程编辑器2
简介流程图拖拽视觉编程-流程编辑器2
目录
一、简介
前期文章:
流程图拖拽视觉编程--概述_Jason~shen的博客-CSDN博客
流程图拖拽视觉编程-流程编辑器_Jason~shen的博客-CSDN博客
本期内容:
本期将继续介绍流程编辑器模块的实现方法,前面介绍了视图的实现,现在介绍自定义图元的实现,即流程图中每个节点块、端口和连接线。
二、自定义图元
该部分基于QGraphicsItem 图元类实现,该类提供了一些基本的图形元件,可在此基础上自定义图元。
2.1图元设计
开始:圆角矩形 + 1个输出端口
结束:圆角矩形 + 1个输入端口
程序块:矩形 + 1个输入端口 + 1个输出端口
条件:菱形 + 1个输入端口 + 1个为真端口 + 1个为假端口
循环:菱形 + 1个输入端口 + 2个循环体端口 (左+下)+ 1个退出循环端口(右)
流程线:带箭头的直线或者折线
2.2 端口QNEPort
继承QGraphicsPathItem,设置为圆形
QPainterPath p;
p.addEllipse(-radius_, -radius_, 2 * radius_, 2 * radius_);
setPath(p);
#ifndef QNEPORT_H
#define QNEPORT_H
#include <QGraphicsPathItem>
#include "floweditor_global.h"
class QNEBlock;
class QNEConnection;
/* 端口 */
class FLOWEDITORSHARED_EXPORT QNEPort : public QGraphicsPathItem
{
public:
enum { Type = QGraphicsItem::UserType + 1 };
enum E_Direction {TOP = 0, BOTTOM = 1, LEFT = 2, RIGHT = 3};
QNEPort(QGraphicsItem *parent = 0);
~QNEPort();
void setDirection(const E_Direction &dir);
E_Direction direction();
void setOutput(bool b);
bool isOutput() const;
void setNEBlock(QNEBlock *);
QNEBlock *block() const;
int radius();
QVector<QNEConnection *> &connections();
bool isConnected(QNEPort *);
int type() const
{
return Type;
}
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
QNEBlock *m_block;
int radius_;
bool m_isOutput;
E_Direction m_directtion;
QVector<QNEConnection *> m_connections;
};
#endif // QNEPORT_H
#include "NEPort.h"
#include <QGraphicsScene>
#include <QFontMetrics>
#include <QPen>
#include <QDebug>
#include "NEConnection.h"
QNEPort::QNEPort(QGraphicsItem *parent):
QGraphicsPathItem(parent), m_isOutput(false)
{
radius_ = 5;
QPainterPath p;
p.addEllipse(-radius_, -radius_, 2 * radius_, 2 * radius_);
setPath(p);
setPen(QPen(Qt::darkRed));
setBrush(Qt::red);
setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
}
QNEPort::~QNEPort()
{
foreach(QNEConnection *conn, m_connections)
{
delete conn;
}
}
void QNEPort::setDirection(const QNEPort::E_Direction &dir)
{
m_directtion = dir;
}
QNEPort::E_Direction QNEPort::direction()
{
return m_directtion;
}
void QNEPort::setOutput(bool b)
{
m_isOutput = b;
}
bool QNEPort::isOutput() const
{
return m_isOutput;
}
void QNEPort::setNEBlock(QNEBlock *b)
{
m_block = b;
}
QNEBlock *QNEPort::block() const
{
return m_block;
}
int QNEPort::radius()
{
return radius_;
}
QVector<QNEConnection *> &QNEPort::connections()
{
return m_connections;
}
bool QNEPort::isConnected(QNEPort *other)
{
qDebug() << "m_connections" << m_connections.size();
foreach(QNEConnection *conn, m_connections)
if (conn->port1() == other || conn->port2() == other)
{
return true;
}
return false;
}
QVariant QNEPort::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == GraphicsItemChange::ItemScenePositionHasChanged)
{
foreach(QNEConnection *conn, m_connections)
{
conn->updatePosFromPorts();
conn->updatePath();
}
}
return value;
}
2.3节点块QNEBlock
继承QGraphicsPathItem
#ifndef QNEBLOCK_H
#define QNEBLOCK_H
#include <QFont>
#include <QGraphicsPathItem>
#include "floweditor_global.h"
#include "TypeDefine.h"
class QNEPort;
class QNEConnection;
USE_NAMESPACE_FLOWEDITOR
class FLOWEDITORSHARED_EXPORT QNEBlock : public QGraphicsPathItem
{
public:
enum { Type = QGraphicsItem::UserType + 3 };
QNEBlock(QGraphicsItem *parent = 0);
void setUuid(const QString &uuid);
QString uuid() const;
void setName(const QString &name);
QString name() const;
void setNodeType(const E_NodeType &type);
E_NodeType nodeType() const;
void initBlockByType();
void setData(const QVariant &data);
QVariant data() const;
void setPixmap(const QPixmap &pm);
void setInitData(const E_NodeType type);
QMap<QString, QStringList> getNodeStrMap();
/* 保存加载 */
void save(T_NodeInfo &);
void load(const T_NodeInfo &);
/* 克隆 */
QNEBlock *clone(int max_uuid);
QNEBlock *clone(QString uuid_str);
/* 获得相连的block */
QNEBlock *getNextBlock(int dir);
/* 端口 */
QVector<QNEPort *> ports();
QNEPort *port(int direction);
int type() const
{
return Type;
}
inline int width() const
{
return m_width;
}
inline int height() const
{
return m_height;
}
inline QPointF center() const
{
return QPointF(m_width / 2, m_height / 2);
}
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
int m_width;
int m_height;
E_NodeType m_nodeType;
QVariant m_data; /**< 携带数据 */
QString m_uuid; /**< 唯一识别码 */
QString m_name; /**< 名称 */
QList<QNEPort *> m_nePortList;
QFont m_font;
QPixmap m_pixmap;
T_NodeInfo m_ni;
bool m_bIsDrawPixmap;
};
#endif // QNEBLOCK_H
设置路径:QPainterPath, 根据类型添加不同的形状,添加圆角矩形addRoundedRect、添加菱形addPolygon
添加端口:QNEBlock和QNEPort绑定为父子关系new QNEPort(this),QNEBlock位置移动时QNEPort也会跟随移动
void QNEBlock::initBlockByType()
{
QPainterPath p;
if(E_NodeType::Start == m_nodeType)
{
/* 圆角矩形 */
p.addRoundedRect(0, 0, m_width, m_height, m_height / 2, m_height / 2);
// 下
QNEPort *port = new QNEPort(this);
port->setPos(m_width / 2, m_height);
port->setNEBlock(this);
port->setOutput(true);
port->setToolTip("Out");
port->setDirection(QNEPort::BOTTOM);
}
else if(E_NodeType::End == m_nodeType)
{
/* 圆角矩形 */
p.addRoundedRect(0, 0, m_width, m_height, m_height / 2, m_height / 2);
// 上
QNEPort *port = new QNEPort(this);
port->setPos(m_width / 2, 0);
port->setNEBlock(this);
port->setOutput(false);
port->setToolTip("In");
port->setDirection(QNEPort::TOP);
}
else if(E_NodeType::Judge == m_nodeType)
{
/* 菱形 */
QPolygonF polygonf;
polygonf << QPointF(0, m_height / 2)
<< QPointF(m_width / 2, m_height)
<< QPointF(m_width, m_height / 2)
<< QPointF(m_width / 2, 0)
<< QPointF(0, m_height / 2);
p.addPolygon(polygonf);
// 上
QNEPort *port = new QNEPort(this);
port->setPos(m_width / 2, 0);
port->setNEBlock(this);
port->setOutput(false);
port->setToolTip("In");
port->setDirection(QNEPort::TOP);
// 右
port = new QNEPort(this);
port->setPos(m_width, m_height / 2);
port->setNEBlock(this);
port->setOutput(true);
port->setToolTip("Out");
port->setDirection(QNEPort::RIGHT);
// 下
port = new QNEPort(this);
port->setPos(m_width / 2, m_height);
port->setNEBlock(this);
port->setOutput(true);
port->setToolTip("Out");
port->setDirection(QNEPort::BOTTOM);
}
else if(E_NodeType::Loop == m_nodeType)
{
/* 菱形 */
QPolygonF polygonf;
polygonf << QPointF(0, m_height / 2)
<< QPointF(m_width / 2, m_height)
<< QPointF(m_width, m_height / 2)
<< QPointF(m_width / 2, 0)
<< QPointF(0, m_height / 2);
p.addPolygon(polygonf);
// 上
QNEPort *port = new QNEPort(this);
port->setPos(m_width / 2, 0);
port->setNEBlock(this);
port->setOutput(false);
port->setToolTip("In");
port->setDirection(QNEPort::TOP);
// 右
port = new QNEPort(this);
port->setPos(m_width, m_height / 2);
port->setNEBlock(this);
port->setOutput(true);
port->setToolTip("Out");
port->setDirection(QNEPort::RIGHT);
// 下
port = new QNEPort(this);
port->setPos(m_width / 2, m_height);
port->setNEBlock(this);
port->setOutput(true);
port->setToolTip("Out");
port->setDirection(QNEPort::BOTTOM);
// 左
port = new QNEPort(this);
port->setPos(0, m_height / 2);
port->setNEBlock(this);
port->setOutput(false);
port->setToolTip("In");
port->setDirection(QNEPort::LEFT);
}
else
{
/* 圆角矩形 */
p.addRoundedRect(0, 0, m_width, m_height, 5, 5);
// 上
QNEPort *port = new QNEPort(this);
port->setPos(m_width / 2, 0);
port->setNEBlock(this);
port->setOutput(false);
port->setToolTip("In");
port->setDirection(QNEPort::TOP);
// 下
port = new QNEPort(this);
port->setPos(m_width / 2, m_height);
port->setNEBlock(this);
port->setOutput(true);
port->setToolTip("Out");
port->setDirection(QNEPort::BOTTOM);
m_bIsDrawPixmap = true;
}
setPath(p);
}
重写绘图函数paint(), 选中时端口显示port->show(),未选中时端口隐藏port->hide(),绘制路径drawPath、图片drawPixmap、文字drawText
void QNEBlock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
if (isSelected())
{
painter->setPen(QPen(Qt::darkYellow));
painter->setBrush(Qt::yellow);
foreach(QGraphicsItem *port_, childItems())
{
if (port_->type() == QNEPort::Type)
{
port_->show();
}
}
}
else
{
painter->setPen(QPen(Qt::darkGreen));
painter->setBrush(Qt::green);
foreach(QGraphicsItem *port_, childItems())
{
if (port_->type() == QNEPort::Type)
{
port_->hide();
}
}
}
painter->drawPath(path());
if(m_bIsDrawPixmap && !m_pixmap.isNull())
{
QRect rect(m_height * 0.25, m_height * 0.25, m_height * 0.5, m_height * 0.5);
painter->drawPixmap(rect, m_pixmap);
}
if(!m_name.isEmpty())
{
painter->setPen(QPen(Qt::black));
painter->setBrush(Qt::BrushStyle::NoBrush);
painter->setFont(m_font);
QTextOption option(Qt::AlignCenter);
option.setWrapMode(QTextOption::WordWrap);
painter->drawText(boundingRect(), m_uuid + m_name, option);
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。