qt绘制网络拓补图(连接数据库,递归函数,无限绘制,可拖动节点)

硬件:ThinkPadT590

系统:Win10

数据库:sqlserver2014

Qt:5.14.1

QtCreator:4.11.1

源码连接:

qt绘制网络拓补图(连接数据库,递归函数,无限绘制,可拖动节点)-QT文档类资源-CSDN下载qt实现的绘制网络拓补图,先连接sqlserver数据库获取所有节点数据,然后通过递归函数解析出每个更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/weixin_43935474/85868401

qt实现的绘制网络拓补图,先连接sqlserver数据库获取所有节点数据,然后通过递归函数解析出每个节点之间的关系,并计算每个节点要在图上绘制的位置,然后通过重写的

QGraphicsPixmapItem类来绘制节点图,通过重写的
QGraphicsItem类来绘制节点之间的连线。
只要各节点之间的关系数据正确,可以无限绘制。

界面显示如下:

 拖动效果如下:

 sqlserver数据库表内数据如下:

 关键代码如下: 

#include <QtWidgets>
#include "nodeframe.h"

#include <iostream>
using namespace std;

NodeFrame::NodeFrame(QWidget *parent) :
    QGraphicsView(parent)
{   
    setGeometry(0,0,1920,2000);
    m_scene = new QGraphicsScene(0, 0, this->width(), this->height());
    this->setScene(m_scene);
    QScrollBar *horBar = this->horizontalScrollBar();
    QScrollBar *verBar = this->verticalScrollBar();
    horBar->setValue(horBar->maximum());
    verBar->setValue(verBar->maximum());
//    connectSqlServer();//连接数据库并读取数据,这里先禁用,如果你配好了数据库,则可以开起来
    manulInitNoteList();//如果不连接数据库则可以手动初始化节点队列,连接数据库的情况下,这行要禁用!
    initNodeList();
}

void NodeFrame::manulInitNoteList()
{
    NodeInSql node;
    node.nNodeID =1;    node.nParentID =1;    node.strNodeName ="根节点";    m_lstNodeInSql.append(node);
    node.nNodeID =2;    node.nParentID =1;    node.strNodeName ="子节点2";    m_lstNodeInSql.append(node);
    node.nNodeID =3;    node.nParentID =1;    node.strNodeName ="子节点3";    m_lstNodeInSql.append(node);
    node.nNodeID =4;    node.nParentID =1;    node.strNodeName ="子节点4";    m_lstNodeInSql.append(node);
    node.nNodeID =5;    node.nParentID =1;    node.strNodeName ="子节点5";    m_lstNodeInSql.append(node);
    node.nNodeID =6;    node.nParentID =2;    node.strNodeName ="子节点6";    m_lstNodeInSql.append(node);
    node.nNodeID =7;    node.nParentID =2;    node.strNodeName ="子节点7";    m_lstNodeInSql.append(node);
    node.nNodeID =8;    node.nParentID =3;    node.strNodeName ="子节点8";    m_lstNodeInSql.append(node);
    node.nNodeID =9;    node.nParentID =3;    node.strNodeName ="子节点9";    m_lstNodeInSql.append(node);
    node.nNodeID =10;    node.nParentID =4;    node.strNodeName ="子节点10";    m_lstNodeInSql.append(node);
    node.nNodeID =11;    node.nParentID =10;    node.strNodeName ="子节点11";    m_lstNodeInSql.append(node);
    node.nNodeID =12;    node.nParentID =11;    node.strNodeName ="子节点12";    m_lstNodeInSql.append(node);
    node.nNodeID =13;    node.nParentID =12;    node.strNodeName ="子节点13";    m_lstNodeInSql.append(node);
    node.nNodeID =14;    node.nParentID =13;    node.strNodeName ="子节点14";    m_lstNodeInSql.append(node);
    node.nNodeID =15;    node.nParentID =13;    node.strNodeName ="子节点15";    m_lstNodeInSql.append(node);
    node.nNodeID =16;    node.nParentID =13;    node.strNodeName ="子节点16";    m_lstNodeInSql.append(node);
    node.nNodeID =17;    node.nParentID =13;    node.strNodeName ="子节点17";    m_lstNodeInSql.append(node);
    node.nNodeID =18;    node.nParentID =13;    node.strNodeName ="子节点18";    m_lstNodeInSql.append(node);
}
NodeFrame::~NodeFrame()
{
    delete m_scene;
}


void NodeFrame::refresh()
{
    this->destroyed(m_scene);
    m_scene = new QGraphicsScene(0, 0, this->width(), this->height());
    this->setScene(m_scene);
    initNodeList();
}

void NodeFrame::connectSqlServer()
{
    QSqlDatabase db= QSqlDatabase::addDatabase("QODBC", "dbTemp");
    db.setDatabaseName(QString("DRIVER={SQL SERVER};"
                               "SERVER=%1;" //服务器名称
                               "DATABASE=%2;"//数据库名
                               "UID=%3;"           //登录名
                               "PWD=%4;"        //密码
                               ).arg("127.0.0.1,49674")//我电脑上的端口号是49674
                       .arg("myTestSql")
                       .arg("Bruce")
                       .arg("Qwerty*963.-+")
                       );
    //数据库连接
    bool ok = db.open();
    if(ok)
    {
        qDebug()<<"database open success";
    }
    else
    {
        qDebug()<<db.lastError();
        return;
    }
    //数据库查询
    QSqlQuery query(db);
    query.exec("SELECT * FROM Node;");
    while(query.next())
    {
        NodeInSql node;
        if(query.value(1).isValid())
            node.nNodeID = query.value(1).toInt();
        if(query.value(2).isValid())
            node.nParentID = query.value(2).toInt();
        if(query.value(3).isValid())
            node.strNodeName = query.value(3).toString();
        m_lstNodeInSql.append(node);
    }
    db.close();
}


void NodeFrame::initNodeList()
{
    //找到根节点
    NodeInSql nRootID;
    foreach(NodeInSql node,m_lstNodeInSql)
    {
        if(node.nNodeID==node.nParentID)
        {
            nRootID = node;
        }
    }
    NodeInfoToShow rootNodeInfoToShow;
    rootNodeInfoToShow.nLevel = 0;
    rootNodeInfoToShow.nNodeID = nRootID.nNodeID;
    rootNodeInfoToShow.nParentID = nRootID.nParentID;
    rootNodeInfoToShow.ptPos = QPoint(0,100);
    rootNodeInfoToShow.strNodeName = nRootID.strNodeName;
    m_lstNodeInfoToShow.append(rootNodeInfoToShow);
    NetNode *rootNetNode = new NetNode(rootNodeInfoToShow,m_scene);
    parseNodesInSql(rootNodeInfoToShow,rootNetNode);//解析所有节点关系及位置
}
void NodeFrame::parseNodesInSql(NodeInfoToShow node,NetNode *netNode)
{
    int nChildNum = 0;//当前node节点有几个子节点
    int nWidth = node.nLevel%2==0?250:150;//节点之间的横向间隔
    int nHeight = 200;//节点之间的纵向间隔
    QList<NodeInfoToShow> lstNodeInCrtLevel;//当前node下的所有节点
    for(int i = 0;i<m_lstNodeInSql.count();i++)
    {
        if(m_lstNodeInSql[i].nParentID==node.nNodeID && m_lstNodeInSql[i].nParentID!=m_lstNodeInSql[i].nNodeID)
        {
            nChildNum++;
            NodeInfoToShow rootNodeInfoToShow;
            rootNodeInfoToShow.nLevel = node.nLevel+1;
            rootNodeInfoToShow.nNodeID = m_lstNodeInSql[i].nNodeID;
            rootNodeInfoToShow.nParentID = node.nNodeID;
            rootNodeInfoToShow.ptPos = QPoint(0,0);//这里先给0,0点作为初始值,下面再给每个子节点确定位置
            rootNodeInfoToShow.strNodeName = m_lstNodeInSql[i].strNodeName;
            lstNodeInCrtLevel.append(rootNodeInfoToShow);
        }
    }
    //确定每个子节点的位置
    for(int i = 0;i<lstNodeInCrtLevel.count();i++)
    {
        if(nChildNum%2==1)//有奇数个子节点
        {
            int nHalf = (nChildNum-1)/2;
            int nX =node.ptPos.x()+(i-nHalf)*nWidth;//以上一个节点的x坐标为基础加上偏移量
            int nY = node.ptPos.y()+nHeight;//以上一个节点的y坐标为基础加上偏移量
            lstNodeInCrtLevel[i].ptPos = QPoint(nX,nY);
        }
        else//有偶数个子节点
        {
            int nHalf = nChildNum/2;
            int nX =node.ptPos.x()+(i-nHalf)*nWidth+nWidth/2;//以上一个节点的x坐标为基础加上偏移量
            int nY = node.ptPos.y()+nHeight;//以上一个节点的y坐标为基础加上偏移量
            lstNodeInCrtLevel[i].ptPos = QPoint(nX,nY);
        }
        m_lstNodeInfoToShow.append(lstNodeInCrtLevel[i]);
        NetNode *subNetNode = new NetNode(lstNodeInCrtLevel[i],m_scene);
        NodeLink *link = new NodeLink(netNode, subNetNode);
        if (link) {
            m_scene->addItem(link);
        }
        parseNodesInSql(lstNodeInCrtLevel[i],subNetNode);
    }
}

源码下载连接:

qt绘制网络拓补图(连接数据库,递归函数,无限绘制,可拖动节点)-QT文档类资源-CSDN下载qt实现的绘制网络拓补图,先连接sqlserver数据库获取所有节点数据,然后通过递归函数解析出每个更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/weixin_43935474/85868401

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GreenHandBruce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值