【问题标题】:Remove nodes with mouse click, networkX, python 2.7用鼠标点击删除节点,networkX,python 2.7
【发布时间】:2015-07-29 03:21:28
【问题描述】:

我在 Python 2.7 中使用 networkX 编写了一个程序,它绘制了一棵带有黑白节点的树。这是一个最小的例子:

import networkx as nx
import matplotlib.pyplot as plt
import numpy

T = nx.Graph()

### Nodes
white, black = [1, 4, 5, 6, 7], [2, 3]
allNodes = white+black

for node in allNodes:      T.add_node(node)

### Edges
T.add_edge(1, 2)
T.add_edge(1, 3)
T.add_edge(2, 4)
T.add_edge(2, 5)
T.add_edge(3, 6)
T.add_edge(3, 7)

### Positions of the nodes
pos={}
pos[1]=numpy.array([ 0,0])
pos[2]=numpy.array([-2,1])
pos[3]=numpy.array([ 2,1])
pos[4]=numpy.array([-3,2])
pos[5]=numpy.array([-1,2])
pos[6]=numpy.array([ 1,2])
pos[7]=numpy.array([ 3,2])

### Draw nodes and edges
nx.draw_networkx_nodes(T, pos, nodelist=black, node_color='k',     node_size=400,     alpha=0.8)
nx.draw_networkx_nodes(T, pos, nodelist=white, node_color='w',     node_size=400,     alpha=0.8)
nx.draw_networkx_edges(T,pos,width=1.0, alpha=0.5)

plt.axis('off')     # Remove the axes
plt.show()          # Show the tree

代码创建了一个窗口,其中有一棵包含 7 个节点和 6 条边的小树。现在,当我用鼠标单击它们时,我希望节点消失。我该怎么做?

稍后我的计划是让 2 名玩家轮流交替,移除颜色(黑色和白色)中的叶子或根。 IE。玩家1只能去除黑叶或黑根,玩家2只能去除白叶和白根。

我发现这些链接可能会有所帮助,但无法使用:

谁知道如何做到这一点或有一些提示?

【问题讨论】:

  • 恐怕我帮不上什么忙,但要澄清你的问题:你想让他们从情节中消失吗?还是从图表中删除?
  • 从情节上看,它们也可能从树上消失。

标签: python-2.7 matplotlib networkx interactive


【解决方案1】:

我一直在寻找如何通过鼠标单击构建 networkx 图形的示例,并被重定向到此处。所以我重构了一段代码,让它更短,修复和优化了错误。我正在使用 Python 3.8 和 Networkx 2.5。

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import scipy.spatial

def onClick(event, G):
    if event.inaxes is not None and len(G.nodes()) > 0:
        nodelist, coords = zip(*nx.get_node_attributes(G, 'pos').items())
        kdtree = scipy.spatial.KDTree(coords)
        xy = np.array([event.xdata, event.ydata])
        close_idx = kdtree.query_ball_point(xy, np.sqrt(0.1))
        for i in close_idx:
            G.remove_node(nodelist[i])
        refreshGraph(G)

def refreshGraph(G):
    plt.clf()
    nx.draw_networkx_nodes(G, pos = nx.get_node_attributes(G, 'pos'), node_color='k', node_size=400, alpha=0.8)
    nx.draw_networkx_edges(G, pos = nx.get_node_attributes(G, 'pos'), width=1.0, alpha=0.5)
    plt.axis('off')
    plt.axis((-4, 4, -1, 3))
    fig.patch.set_facecolor('white')
    plt.show()

#Parameters of graph
nodes = np.array(['A','B','C','D','E','F','G'])
edges = np.array([['A', 'B'], ['A', 'C'], ['B', 'D'], ['B', 'E'], ['C', 'F'], ['C', 'G']])
pos = np.array([[ 0,0], [-2,1], [ 2,1], [-3,2], [-1,2], [ 1,2], [ 3,2]])

G = nx.Graph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
nx.set_node_attributes(G, dict(zip(G.nodes(), pos)), 'pos')

fig, ax = plt.subplots()
fig.canvas.mpl_connect('button_press_event', lambda event, G=G: onClick(event, G))
refreshGraph(G)

这是此处改进的内容列表:

  • nodesedgespos 可以使用 numpy 数组一键设置。
  • 没有使用着色来制作 MWE。
  • 图外不需要全局存储节点; pos 是图本身的一个属性。
  • graph 是 onClickrefreshGraph 的参数,因此不需要全局变量来使这些函数工作
  • KDtrees 的帮助下优化了关闭节点的查找,如果有大量节点,则不会出现延迟。
  • 修复了在图表外单击图表时计算鼠标位置的错误。
  • 支持删除点击半径内的多个节点。

【讨论】:

    【解决方案2】:

    我成功了!我不得不从情节中保存“无花果”和“斧头”(我认为它是图形和轴?)。然后我可以将我称为 onClick 的方法/函数连接到对鼠标点击做出反应的图形('button_press_event')。

    这里如何从图中获取“fig”和“ax”并连接函数/方法:

    fig, ax = plt.subplots()
    fig.canvas.mpl_connect('button_press_event', onClick)
    

    这是从图形和绘图中删除节点的方法

    def onClick(event):
        (x,y)   = (event.xdata, event.ydata)
    
        for i in allNodes:            
            node = pos[i]
            distance = pow(x-node[0],2)+pow(y-node[1],2)
            if distance < 0.1:
                T.remove_node(i)
                if i in black: black.remove(i)
                if i in white: white.remove(i)
                allNodes.remove(i)
                refreshGraph()    
    

    整个代码:

    import networkx as nx
    import matplotlib.pyplot as plt
    import numpy
    import numpy as np
    import pylab
    
    def refreshGraph():
        plt.clf()
        nx.draw_networkx_nodes(T, pos, nodelist=black, node_color='k', node_size=400, alpha=0.8)
        nx.draw_networkx_nodes(T, pos, nodelist=white, node_color='w', node_size=400, alpha=0.8)
        nx.draw_networkx_edges(T,pos,width=1.0, alpha=0.5)
        plt.axis('off')
        plt.axis((-4,4,-1,3))
        fig.patch.set_facecolor('white')
        plt.show()
    
    def onClick(event):
        (x,y)   = (event.xdata, event.ydata)
    
        for i in allNodes:            
            node = pos[i]
            distance = pow(x-node[0],2)+pow(y-node[1],2)
            if distance < 0.1:
                T.remove_node(i)
                if i in black: black.remove(i)
                if i in white: white.remove(i)
                allNodes.remove(i)
                refreshGraph()
    
    fig, ax = plt.subplots()
    fig.canvas.mpl_connect('button_press_event', onClick)
    
    T = nx.Graph()
    
    ### Nodes
    white, black = [1, 4, 5, 6, 7], [2, 3]
    allNodes = white+black
    
    for node in allNodes:      T.add_node(node)
    
    ### Edges
    T.add_edge(1, 2)
    T.add_edge(1, 3)
    T.add_edge(2, 4)
    T.add_edge(2, 5)
    T.add_edge(3, 6)
    T.add_edge(3, 7)
    
    ### Positions of the nodes
    pos={}
    pos[1]=numpy.array([ 0,0])
    pos[2]=numpy.array([-2,1])
    pos[3]=numpy.array([ 2,1])
    pos[4]=numpy.array([-3,2])
    pos[5]=numpy.array([-1,2])
    pos[6]=numpy.array([ 1,2])
    pos[7]=numpy.array([ 3,2])
    
    ### Draw nodes and edges
    refreshGraph()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 2018-05-08
      • 2013-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多