目錄
一、簡介
二、流程編輯器-視圖實現(xiàn)
三、參考資料
一、簡介
前期文章:
流程圖拖拽視覺編程--概述_Jason~shen的博客-CSDN博客
本期內(nèi)容:
本期將介紹流程編輯器模塊的實現(xiàn)方法,效果圖如下所示。該模塊基于QT Graphics/View實現(xiàn),由視圖、自定義圖元、圖元管理器組成。
二、流程編輯器-視圖實現(xiàn)
視圖的功能是提供一個節(jié)點顯示窗口,支持縮放、平移和網(wǎng)格線背景。
該部分繼承QGraphicsView實現(xiàn),定義接口如下:
class GRAPHICSLIBSHARED_EXPORT BaseGraphicsView: public QGraphicsView
{
Q_OBJECT
public:
explicit BaseGraphicsView(QWidget *parent = nullptr);
~BaseGraphicsView();
void setFactorMax(double val); //最大縮放因子
void setFactorMin(double val); //最小縮放因子
void setShowGrid(bool b); //是否顯示網(wǎng)格線
void setMoveSceneEnabled(bool b); //是否平移使能
public slots:
void zoomIn();
void zoomOut();
protected:
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
void drawBackground(QPainter *painter, const QRectF &rect) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
private:
void drawGrid(QPainter *painter, double gridStep);
private:
double m_factorMax;
double m_factorMin;
QPointF m_scenePos;
QPointF m_pressPos;
bool m_moveScene;
bool m_showGrid;
bool m_moveSceneEnabled;
};
縮放的實現(xiàn):核心函數(shù)scale(), 配合鼠標事件操作,重寫鼠標滾動事件函數(shù)wheelEvent,限制視圖過大或者過小。
void BaseGraphicsView::zoomIn()
{
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
scale(1.2, 1.2);
}
void BaseGraphicsView::zoomOut()
{
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
scale(1 / 1.2, 1 / 1.2);
}
void BaseGraphicsView::wheelEvent(QWheelEvent *event)
{
qreal factor_out = transform().scale(1.2, 1.2).mapRect(QRectF(0, 0, 1, 1)).width();
qreal factor_in = transform().scale(1 / 1.2, 1 / 1.2).mapRect(QRectF(0, 0, 1, 1)).width();
if (event->delta() > 0)
{
if(factor_out > m_factorMax)
{
return; /* 防止視圖過大 */
}
zoomIn();
}
else
{
if(factor_in < m_factorMin)
{
return; /* 防止視圖過小 */
}
zoomOut();
}
update();
}
平移的實現(xiàn):?核心函數(shù)setSceneRect(),配合鼠標事件操作,重寫鼠標按下mousePressEvent、移動mouseMoveEvent、釋放mouseReleaseEvent事件函數(shù)。
void BaseGraphicsView::mousePressEvent(QMouseEvent *event)
{
if(m_moveSceneEnabled)
{
QMouseEvent fake(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers());
m_scenePos = mapToScene(event->pos());
m_pressPos = m_scenePos;
setDragMode(QGraphicsView::NoDrag);
if (QApplication::keyboardModifiers() == Qt::ControlModifier &&
event->button() == Qt::LeftButton)
{
setDragMode(QGraphicsView::RubberBandDrag);
}
if (event->button() == Qt::MiddleButton)
{
setDragMode(QGraphicsView::ScrollHandDrag);
setInteractive(false);
event = &fake;
m_moveScene = true;
}
update();
}
QGraphicsView::mousePressEvent(event);
}
void BaseGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if(m_moveSceneEnabled)
{
m_scenePos = mapToScene(event->pos());
if (m_moveScene)
{
QPointF difference = m_pressPos - m_scenePos;
setSceneRect(sceneRect().translated(difference.x(), difference.y()));
}
update();
}
QGraphicsView::mouseMoveEvent(event);
}
void BaseGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if(m_moveSceneEnabled)
{
QMouseEvent fake(event->type(), event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers());
if (event->button() == Qt::MiddleButton)
{
setDragMode(QGraphicsView::NoDrag);
setInteractive(true);
event = &fake;
}
m_moveScene = false;
update();
}
QGraphicsView::mouseReleaseEvent(event);
}
網(wǎng)格線背景,通過繪圖類QPainter畫線,重寫繪制背景函數(shù)drawBackground
void BaseGraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
{
QGraphicsView::drawBackground(painter, rect);
if(m_showGrid)
{
QPen pfine(QColor::fromRgb(50, 50, 50), 0.6);
painter->setPen(pfine);
drawGrid(painter, 15);
QPen p(QColor::fromRgb(50, 50, 50), 2.0);
painter->setPen(p);
drawGrid(painter, 150);
}
}
void BaseGraphicsView::drawGrid(QPainter *painter, double gridStep)
{
QRect windowRect = rect();
QPointF tl = mapToScene(windowRect.topLeft());
QPointF br = mapToScene(windowRect.bottomRight());
double left = qFloor(tl.x() / gridStep - 0.5);
double right = qFloor(br.x() / gridStep + 1.0);
double bottom = qFloor(tl.y() / gridStep - 0.5);
double top = qFloor(br.y() / gridStep + 1.0);
for (int xi = int(left); xi <= int(right); ++xi)
{
QLineF line(xi * gridStep, bottom * gridStep,
xi * gridStep, top * gridStep );
painter->drawLine(line);
}
for (int yi = int(bottom); yi <= int(top); ++yi)
{
QLineF line(left * gridStep, yi * gridStep,
right * gridStep, yi * gridStep );
painter->drawLine(line);
}
}
三、參考資料
文章
GitHub開源推薦 | 節(jié)點編輯器-技術圈
python版本
Pavel K?upala / pyqt-node-editor · GitLab
https://blog.csdn.net/mahuatengmmp/category_9948511.html
Release v0.3.1 · beyse/NodeEditor · GitHub
qt4/qt5版本
GitHub - Buanderie/qnodeseditor: Originally from http://algoholic.eu/qnodeseditor-qt-nodesports-based-data-processing-flow-editor/文章來源:http://www.zghlxwxcb.cn/news/detail-447157.html
GitHub - hzt1234hf/FlowChartTools: 使用QT開發(fā)的跨平臺(Windows、Linux)流程圖繪制工具文章來源地址http://www.zghlxwxcb.cn/news/detail-447157.html
到了這里,關于流程圖拖拽視覺編程-流程編輯器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!