I'm developing a project in Python where I use the tkinter library to display the GUI of my application. The problem that i face is the need to present a network graph in my program. I've already discovered the NetworkX library that allows me to create this graph but I don't know how to display it in a tkinter window. Any ideas on how to implement?
I have already tried several approaches to the problem of creating the network graph, such as trying to create the graph from the browser and placing the browser in a tkinter window, I have tried just using tkinter to create the graph but I was unsuccessful in both, after searching on the internet I found this NetworkX library but I don't know how I can integrate the graph obtained in a tkinter window
networkx
uses matplotlib
to display it.
And matplotlib
has special methods to embed plot in tkinter
(or in PyQt
).
Doc: Embedding in Tk — Matplotlib 3.9.0 documentation
Create fig
and ax
as usually in matplotlib
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot()
and use fig
to create tkinter widget
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(fill='both', expand=True)
#canvas.draw()
and use ax
in draw(..., ax=ax)
to display it in widget
nx.draw(G, with_labels=True, font_weight='bold', ax=ax)
Sometimes it needs to update content on canvas
canvas.draw() # update plot in widget
Minimal working code:
import networkx as nx
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
# --- create figure and axis for plot
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot()
# --- create widgets - special canvas to display matplotlib plot
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(fill='both', expand=True)
#canvas.draw() # update plot in widget
# --- create graph
G = nx.Graph()
G.add_nodes_from([1, 2, 3, 4])
G.add_edges_from([(1, 2), (3, 4), (1,4), (2, 3)])
# --- draw graph using `ax=ax`
nx.draw(G, with_labels=True, font_weight='bold', ax=ax)
#canvas.draw() # update plot in widget
# ---
button_quit = tkinter.Button(root, text="Quit", command=root.destroy)
button_quit.pack()
tkinter.mainloop()
EDIT:
Another example which uses Button
to replace graph in window.
I also put some code in different order to show that you can draw before you create widget.
It also has to use canvas.draw()
in function change_graph()
to display new graph.
import networkx as nx
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import random
def change_graph():
#nodes = [1, 2, 3, 4, 5, 6]
#edges = [(1, 2), (3, 4), (1,4), (2, 3), (4, 5), (5, 6)]
n = random.randint(4, 10)
nodes = list(range(n))
edges = [random.sample(nodes, 2) for _ in range(2*n)]
G = nx.Graph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
ax.clear() # remove previous graph
nx.draw(G, with_labels=True, font_weight='bold', ax=ax)
canvas.draw() # it needs it in this place
# --- create graph
G = nx.Graph()
G.add_nodes_from([1, 2, 3, 4])
G.add_edges_from([(1, 2), (3, 4), (1,4), (2, 3)])
# ---
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
# --- create figure and axis
# --- draw graph using `ax=ax`
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot()
nx.draw(G, with_labels=True, font_weight='bold', ax=ax)
#canvas.draw()
# --- create widgets
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(fill='both', expand=True)
#canvas.draw()
# --- other elements in window
button_change = tkinter.Button(root, text="Change Graph", command=change_graph)
button_change.pack(fill='x')
button_quit = tkinter.Button(root, text="Quit", command=root.destroy)
button_quit.pack(fill='x')
tkinter.mainloop()