I can draw a directed network graph using Matplotlib. Now I want to be able to respond to mouse events so that a user can interact with the network. For example, a node could change its colour when the user clicks on it. This is just a noddy example but it illustrates the point. I'd also like to know which node (label) has been clicked on; I'm not really interested in its x,y coordinates in space.
Here's my code so far:
import matplotlib.pyplot as plt
from matplotlib.collections import PathCollection
import networkx as nx
def createDiGraph():
G = nx.DiGraph()
# Add nodes:
nodes = ['A', 'B', 'C', 'D', 'E']
G.add_nodes_from(nodes)
# Add edges or links between the nodes:
edges = [('A','B'), ('B','C'), ('B', 'D'), ('D', 'E')]
G.add_edges_from(edges)
return G
G = createDiGraph()
# Get a layout for the nodes according to some algorithm.
pos = nx.layout.spring_layout(G, random_state=779)
node_size = 300
nodes = nx.draw_networkx_nodes(G, pos, node_size=node_size, node_color=(0,0,0.9),
edgecolors='black')
# nodes is a matplotlib.collections.PathCollection object
nodes.set_picker(5)
#nodes.pick('button_press_event')
#print(nodes.get_offsets())
nx.draw_networkx_edges(G, pos, node_size=node_size, arrowstyle='->',
arrowsize=15, edge_color='black', width=1)
nx.draw_networkx_labels(G, pos, font_color='red', font_family='arial',
font_size=10)
def onpick(event):
#print(event.mouseevent)
if isinstance(event.artist, PathCollection):
#nodes = event.artist
print (event.ind)
fig = plt.gcf()
# Bind our onpick() function to pick events:
fig.canvas.mpl_connect('pick_event', onpick)
# Hide the axes:
plt.gca().set_axis_off()
plt.show()
The network looks like this when plotted:
If I click with my mouse on node C for example, the program prints out [1]
; or [3]
for node E. Notice the index doesn't correspond to 0 for A, 1 for B, 2 for C, and so on, even though the original nodes were added to the networkx digraph in that order.
So how do I get the value 'C', when I click on node C? And how do I get hold of the object representing C in the figure so I can change its colour?
I've tried playing around with PathCollection.pick
but I'm not sure what to pass into it and I'm not sure that's the right method to use anyway.