python networkx绘制动态节点

使用networkx生成绘制节点的原始数据,使用matplotlib.pyplot进行绘制,使用了canvas.mpl_connect鼠标事件绑定,使图形根据数据更新动起来,直接上代码结果!鼠标左键点击新增节点;右键点击删除该节点下的其他节点,保留主节点;中间点击显示该节点详细信息。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2022/10/2 16:51
# @Author : singweek
# @File: Plt_Tree

import networkx as nx
import matplotlib.pyplot as plt

"""创建图"""
# G=nx.Graph()#无多重边无向图。忽略两个节点之间的多个边,允许节点自身成环。
# G = nx.DiGraph()#无多重边有向图
# G=nx.MultiGraph()#有多重边无向图,允许在成对的节点之间存在多个无向边。
# G=nx.MultiDiGraph()#有多重边有向图
# G = nx.davis_southern_women_graph()#构造关系图

"""新增节点边界以及删除节点边界"""
# G.add_node("start", subset=0)#添加节点
# G.add_nodes_from([1,2,3,4,5],weight=1)
# G.add_edges_from([('start','2'),('start','3')])#更新多个边界新信息,新增连接
# G.add_edge(('3', '5'))#更新单个边界信息
# G.remove_edges_from([('start','2'),('start','3')])#删除多个边界信息,start-2
# G.remove_edge(('start','2'))#删除单个边界信息
# G.remove_node()
# G.remove_nodes_from()

"""绘制节点显示"""
# nx.draw(G, pos, with_labels=True, node_color=node_color_l, edge_color=edge_color, node_size=1000)  # ,with_labels=True
# # 展示
# plt.show()

def Get_Address_info(address):
    """
    获取显示的数据,自己根据需求修改
    return address_info_dict={'address':"address info"}
    """
    address_info_dict={'start':"address info",'2':'adress 2','3':'adress3'}
    if address in address_info_dict.keys():
        return address_info_dict[address]
    else:
        return ''

def Get_Address_Node(address):
    """
    获取节点数据,可以动态加载,自己根据需求修改
    return address_node_dict={"node_cur":"start","node_pre":[1,2],"node_next":[3,4],"node_pre_color":'g',"node_next_color":'b'}
    """
    Data_dict={'start':{"node_cur":'start','node_pre':['1-0','2-0','3-0'],'node_next':['1-1','2','1-3'],"node_pre_color":'g',"node_next_color":'b'},
               '2':{"node_cur":'2','node_pre':['1','2-1','2-2'],'node_next':['2-1','2-2','3'],"node_pre_color":'g',"node_next_color":'b'},
               '3':{"node_cur":'3','node_pre':['3-1','3-3','3-2'],'node_next':['3-4','3-5','4'],"node_pre_color":'g',"node_next_color":'b'}}
    # address_node_dict={"node_cur":"start","node_pre":[1,2],"node_next":[3,4],"node_pre_color":'g',"node_next_color":'b'}
    if address in Data_dict.keys():
        return Data_dict[address]
    else:
        return {}

# 鼠标点击响应函数
def on_press(event,loc,error_xy=0.05):
    """
    鼠标点击事件判断
    event.button        1、2、3分别为鼠标左键、中键、右键点击
    event.x, event.y         显示屏幕的坐标,从左上角开始计算
    event.xdata, event.ydata     绘图中的坐标,从左上角开始计算,0-1范围内
    loc     传入所有节点的参数及坐标
    error_xy    点击坐标误差
    """
    global Node_Line
    print("点击坐标:",'button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %(event.button, event.x, event.y, event.xdata, event.ydata))
    print("节点坐标",loc)
    x,y=event.xdata, event.ydata
    for i in loc.keys():
        tx,ty=loc[i]
        if tx-error_xy<=x<=tx+error_xy and ty-error_xy<=y<=ty+error_xy:
            print("点击节点:",i)
            if event.button==2:#鼠标中键显示节点信息
                address_info=Get_Address_info(i)#获取节点信息,以便用于绘制{'1':'address'}
                if address_info!="":
                    Plt_labels(i,address=address_info)
                    plt.show()
            if event.button==1:#鼠标左键点击,扩张节点
                node_cur_dict=Get_Address_Node(i)#获取节点信息,用于绘制
                if node_cur_dict!={}:
                    node_cur = node_cur_dict['node_cur']
                    node_pre = node_cur_dict['node_pre']
                    node_next = node_cur_dict['node_next']
                    node_pre_color = node_cur_dict['node_pre_color']
                    node_next_color = node_cur_dict['node_next_color']
                    Node_Line.append(node_cur)
                    Add_Refresh_plt(node_cur,node_pre,node_next,node_pre_color=node_pre_color,node_next_color=node_next_color)
            if event.button==3:#鼠标右键点击,删除节点
                node_cur_dict=Get_Address_Node(i)#获取节点信息,用于绘制
                if node_cur_dict != {}:
                    node_cur = node_cur_dict['node_cur']
                    node_pre = node_cur_dict['node_pre']
                    node_next = node_cur_dict['node_next']
                    node_pre_color = node_cur_dict['node_pre_color']
                    node_next_color = node_cur_dict['node_next_color']
                    Delete_Refresh_plt(node_cur, node_pre, node_next,node_pre_color=node_pre_color,node_next_color=node_next_color)

def Add_Refresh_plt(node_cur,node_pre=[],node_next=[],node_pre_color='green',node_next_color='blue',edge_color='black'):
    """
    新增节点,刷新画布
    :param node_cur开始点击的节点
    :param node_pre点击的上一节点[1,2,3]传入当前地址的节点
    :param node_next点击的下一节点[1,2,3]当前节点的输出节点
    # :param node_color节点颜色{1:'r',2:'y'}
    :param node_pre_color新增节点颜色'r'
    :param node_next_color新增节点颜色'y'
    :param edge_color边界颜色'black'默认黑色,所有边界颜色都一样
    """
    global cid,node_color,Node_Line,pos
    pos_o = nx.spring_layout(G)  # 获取绘制前节点位置
    # if node_cur=="start":#暂时定位start
    node_color.update({node_cur: 'red'})  # 修改点击节点颜色,默认红色
    """新增上一节点"""
    for i in node_pre:
        if i not in pos_o.keys():#如果新增节点不在之前绘制的节点内
            G.add_node(i)#新增节点
        node_color.update({i:node_pre_color})#新增节点颜色
    for i in node_pre:
        G.add_edge(node_cur, i)
    """新增下一节点"""
    for i in node_next:
        if i not in pos_o.keys():#如果新增节点不在之前绘制的节点内
            G.add_node(i)#新增节点
        node_color.update({i: node_next_color})  # 新增节点颜色
    for i in node_next:
        G.add_edge(node_cur,i)
    pos = nx.spring_layout(G)  # 获取新增节点位置
    fig.canvas.mpl_disconnect(cid)#解除鼠标事件绑定
    plt.clf()#
    cid=fig.canvas.mpl_connect('button_press_event', lambda event: on_press(event, pos))#鼠标事件绑定
    node_color_l=[node_color[i] for i in node_color.keys()]
    nx.draw(G, pos, with_labels=True, node_color=node_color_l, edge_color=edge_color, node_size=1000)  #绘制
    plt.show()#显示

def Delete_Refresh_plt(node_cur,node_pre=[],node_next=[],node_pre_color='green',node_next_color='blue',edge_color='black'):
    """
    删除节点,刷新画布
    :param node_cur开始点击的节点
    :param node_pre点击的上一节点[1,2,3]传入当前地址的节点
    :param node_next点击的下一节点[1,2,3]当前节点的输出节点
    # :param node_color节点颜色{1:'r',2:'y'}
    :param node_pre_color新增节点颜色'r'
    :param node_next_color新增节点颜色'y'
    :param edge_color边界颜色'black'默认黑色,所有边界颜色都一样
    """
    global cid,node_color,Node_Line,pos
    # pos_o = nx.spring_layout(G)  # 获取绘制前节点位置
    # if node_cur=="start":#暂时定位start
    node_color.update({node_cur: 'red'})  # 修改点击节点颜色,默认红色
    # print("删除节点",node_pre,node_next)
    for i in node_next:#删除下一个节点
        if i not in Node_Line:
            try:
                G.remove_node(i)
                del node_color[i]
            except:
                print("删除出错节点:", i)
    for i in node_pre:#删除上一个节点
        if i not in Node_Line:
            try:
                G.remove_node(i)
                del node_color[i]
            except:
                print("删除出错节点:", i)

    pos = nx.spring_layout(G)  #获取新增节点位置
    fig.canvas.mpl_disconnect(cid)#解除鼠标事件绑定
    plt.clf()#
    cid=fig.canvas.mpl_connect('button_press_event', lambda event: on_press(event, pos))#鼠标事件绑定
    node_color_l=[node_color[i] for i in node_color.keys()]
    nx.draw(G, pos, with_labels=True, node_color=node_color_l, edge_color=edge_color, node_size=1000)  #绘制
    plt.show()#显示

def Plt_labels(node,address="address",error_xy=0.2,font_color='magenta'):
    """
    绘制节点标签
    # :param pos    坐标{'start': array([0.27709403, 0.38102859])}
    :param node   节点名称
    :param  address   绘制参数
    :param error_xy   绘制位置调整
    :param font_color   'magenta'
    """
    # pos = nx.spring_layout(G)  # 获取新增节点位置
    global pos
    xy=pos[node]
    pos_label={'start':[xy[0],xy[1]-error_xy]}
    node_label={'start':address}
    nx.draw_networkx_labels(G, pos_label, labels=node_label,font_color=font_color)


if __name__ == '__main__':
    start_node="start"
    Node_Line = [start_node]
    G = nx.Graph()  # 无多重边无向图。忽略两个节点之间的多个边,允许节点自身成环。
    G.add_node(start_node)
    pos = nx.spring_layout(G)#获取节点位置
    node_color={'start':'red'}#起始节点颜色
    node_color_l=[node_color[i] for i in node_color.keys()]
    edge_color='black'
    fig = plt.figure()
    #绑定鼠标事件
    cid=fig.canvas.mpl_connect('button_press_event',lambda event:on_press(event,pos))
    # networkx画关系图
    nx.draw(G, pos,  with_labels=True,node_color=node_color_l, edge_color=edge_color, node_size=1000)  # ,with_labels=True
    # 展示
    plt.show()

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值