Search code examples
pythontkinternetworkx

How to create in python a network graph, using NetworkX library, and display it in Tkinter window


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


Solution

  • 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()
    

    enter image description here


    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()
    

    enter image description here