pythonmatplotlibpyqt5interactivenetgraph

PyQt and Netgraph Editable Graph


I already have an PyQt application working along with Netgraph.

I am able to move vertex and edges, given the following code:

import sys

from PyQt5 import QtWidgets

import matplotlib

matplotlib.use("Qt5Agg")


from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
from matplotlib.figure import Figure

from netgraph import InteractiveGraph

import networkx as nx


class MplCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        super(MplCanvas, self).__init__(Figure(figsize=(width, height), dpi=dpi))
        self.setParent(parent)
        self.ax = self.figure.add_subplot(111)
        graph = nx.house_x_graph()
        self.plot_instance = InteractiveGraph(graph, ax=self.ax)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
        self.toolbar = NavigationToolbar2QT(self.canvas, self)

        widget = QtWidgets.QWidget()
        self.setCentralWidget(widget)

        layout = QtWidgets.QVBoxLayout(widget)
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)


def main():
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()


if __name__ == "__main__":
    main()

Netgraph EditableGraph allows to add or remove vertex and edges, for example. However, in the previous code, if changed from InteractiveGraph to EditableGraph, nothing is changed.

If you run the following example:

import matplotlib.pyplot as plt
import networkx as nx
from netgraph import EditableGraph

g = nx.house_x_graph()


fig, ax = plt.subplots(figsize=(10, 10))

plot_instance = EditableGraph(g)

plt.show()

Click on every vertex or edge, and then press the delete button, it will be erased.

I want this same behavior inside a PyQt window. I am not sure what is missing.


Solution

  • I got some help opening an issue at netgraph repo and I ended up with the following algorithm:

    import sys
    import matplotlib; matplotlib.use("Qt5Agg")
    
    from PyQt5 import QtWidgets, QtCore # <- additional import
    from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
    from matplotlib.figure import Figure
    from netgraph import EditableGraph
    
    
    class MplCanvas(FigureCanvasQTAgg):
        def __init__(self, parent=None, width=5, height=4, dpi=100):
            super(MplCanvas, self).__init__(Figure(figsize=(width, height), dpi=dpi))
            self.setParent(parent)
            self.ax = self.figure.add_subplot(111)
            self.graph = EditableGraph([(0, 1)], ax=self.ax)
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, *args, **kwargs):
            super(MainWindow, self).__init__(*args, **kwargs)
    
            self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
    
            # ----------------------------------------
            # Enable key_press_event events:
            # https://github.com/matplotlib/matplotlib/issues/707/#issuecomment-4181799
            self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
            self.canvas.setFocus()
            # ----------------------------------------
    
            self.toolbar = NavigationToolbar2QT(self.canvas, self)
    
            widget = QtWidgets.QWidget()
            self.setCentralWidget(widget)
    
            layout = QtWidgets.QVBoxLayout(widget)
            layout.addWidget(self.toolbar)
            layout.addWidget(self.canvas)
    
    
    def main():
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        app.exec_()
    
    
    if __name__ == "__main__":
        main()