Home > Software engineering >  Edge labels of networkx graph don't show in PyQt embedded matplotlib
Edge labels of networkx graph don't show in PyQt embedded matplotlib

Time:09-16

I have networkx directed graph that are displayed in a PyQt5 application which are working perfectly fine. I am now trying to add labels to the edge for some conveniency, but can't manage to make them appear.

Below is a dummy application to replicate the issue:

import sys
from PyQt5 import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.pyplot import Figure
import networkx as nx


class data_tab(QtWidgets.QWidget):

    def __init__(self, parent, title):

        QtWidgets.QWidget.__init__(self, parent)

        self.data_tab_glayout = QtWidgets.QGridLayout(self)
        self.canvas = FigureCanvas(Figure(figsize=(5, 3)))
        self.canvas_vlayout = QtWidgets.QVBoxLayout(self.canvas)
        self.data_tab_glayout.addWidget(self.canvas, 0, 0, 2, 1)

        self.axe = self.canvas.figure.add_subplot(111)
        self.canvas.figure.subplots_adjust(left=0.025, top=0.965, bottom=0.040, right=0.975)
        # add the tab to the parent
        parent.addTab(self, "")

        # set text name
        parent.setTabText(parent.indexOf(self), title)


class spec_writer(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)

        self.showMaximized()

        self.centralwidget = QtWidgets.QWidget(self)
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.core_tab = QtWidgets.QTabWidget(self.centralwidget)
        self.verticalLayout.addWidget(self.core_tab)
        self.add_tab_btn = QtWidgets.QPushButton(self.centralwidget)
        self.verticalLayout.addWidget(self.add_tab_btn)
        self.refresh_tab_btn = QtWidgets.QPushButton(self.centralwidget)
        self.verticalLayout.addWidget(self.refresh_tab_btn)
        self.setCentralWidget(self.centralwidget)

        self.add_tab_btn.setText("Add Tab")
        self.refresh_tab_btn.setText("Refresh Tabs")

        self.core_tab.setEnabled(True)
        self.core_tab.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.core_tab.setElideMode(QtCore.Qt.ElideNone)
        self.core_tab.setDocumentMode(False)
        self.core_tab.setTabsClosable(True)
        self.core_tab.setMovable(True)
        self.core_tab.setTabBarAutoHide(False)

        self.tab_counter = 0

        self.random_tabs = [("a", ["b", "c"]),
                            ("d", ["e", "f", "g"]),
                            ("h", ["i", "j", "k", "l"]),
                            ("m", ["n"]),
                            ("o", ["p", "q"]),
                            ("r", ["s", "t", "u", "v", "w", "x", "y", "z"])]

        self.add_tab_btn.clicked.connect(self.openRandomTab)
        self.refresh_tab_btn.clicked.connect(self.refreshAllTabs)

    def openRandomTab(self):

        tab = data_tab(self.core_tab, "test "   str(self.tab_counter))
        self._drawDataGraph(self.tab_counter % len(self.random_tabs), tab)
        self.tab_counter  = 1

        self.core_tab.setCurrentIndex(self.core_tab.indexOf(tab))


    def _drawDataGraph(self, tabNb, dataWidget):
        dataWidget.axe.cla()

        # 1. draw graph
        producer = self.random_tabs[tabNb][0]
        consumers = self.random_tabs[tabNb][1]

        color_map = []
        DG = nx.DiGraph()
        for cons in consumers:
            DG.add_edge(producer, cons, label="labeltest1")
        for i in range(len(DG.nodes())):
            if i < 1   len(consumers):
                color_map.append("#DCE46F")
            else:
                color_map.append("#6FA2E4")
        pos = nx.shell_layout(DG)
        labels = nx.get_edge_attributes(DG, 'label')
        nx.draw(DG, pos, node_color=color_map, with_labels=True, font_size=8, node_size=1000, node_shape='o', ax= dataWidget.axe)
        nx.draw_networkx_edge_labels(DG, pos, edge_labels=labels)
        dataWidget.canvas.draw()


    def refreshAllTabs(self):

        # loop through all pages and associated to get
        for tab_index in range(self.core_tab.count()):
            data_tab_widget = self.core_tab.widget(tab_index)

            # draw graph
            self._drawDataGraph(tab_index % len(self.random_tabs), data_tab_widget)




sys.argv = ['']
app = QtWidgets.QApplication(sys.argv)
cbtc_spec_writer = spec_writer()
cbtc_spec_writer.show()
app.exec_()

I don't know what holds the labels to show, but when I execute the same code not embedded in a pyqt5 application (so directly with a plt.show()), it works properly. So I guess something is missing from my canvas setup.

EDIT : below is what I want to obtain, but embedded in PyQt5 application. Currently the label "labeltest1" won't show

enter image description here

CodePudding user response:

You also have to pass the axes to draw_networkx_edge_labels. Besides that I have rewritten your code to make it more readable.

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
    QApplication,
    QMainWindow,
    QPushButton,
    QTabWidget,
    QVBoxLayout,
    QWidget,
)

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

import networkx as nx


class DataTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        layout = QVBoxLayout(self)
        self.canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(self.canvas)
        self.ax = self.canvas.figure.add_subplot(111)
        self.canvas.figure.subplots_adjust(
            left=0.025, top=0.965, bottom=0.040, right=0.975
        )


class SpecWriter(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.core_tab = QTabWidget(
            tabShape=QTabWidget.Rounded,
            elideMode=Qt.ElideNone,
            documentMode=False,
            tabsClosable=True,
            movable=True,
            tabBarAutoHide=False,
        )
        self.add_tab_btn = QPushButton("Add Tab")
        self.refresh_tab_btn = QPushButton("Refresh Tabs")

        self.centralwidget = QWidget(self)
        layout = QVBoxLayout(self.centralwidget)
        layout.addWidget(self.core_tab)
        layout.addWidget(self.add_tab_btn)
        layout.addWidget(self.refresh_tab_btn)
        self.setCentralWidget(self.centralwidget)

        self.random_tabs = [
            ("a", ["b", "c"]),
            ("d", ["e", "f", "g"]),
            ("h", ["i", "j", "k", "l"]),
            ("m", ["n"]),
            ("o", ["p", "q"]),
            ("r", ["s", "t", "u", "v", "w", "x", "y", "z"]),
        ]

        self.add_tab_btn.clicked.connect(self.open_random_tab)
        self.refresh_tab_btn.clicked.connect(self.refresh_all_tabs)

    def update_graph(self, ax, tabNb):
        ax.clear()
        producer, consumers = self.random_tabs[tabNb]

        color_map = []
        DG = nx.DiGraph()
        for cons in consumers:
            DG.add_edge(producer, cons, label="labeltest1")
        for i, _ in enumerate(DG.nodes()):
            color_map.append("#DCE46F" if i < 1   len(consumers) else "#6FA2E4")
        pos = nx.shell_layout(DG)
        labels = nx.get_edge_attributes(DG, "label")

        nx.draw(
            DG,
            pos,
            node_color=color_map,
            with_labels=True,
            font_size=8,
            node_size=1000,
            node_shape="o",
            ax=ax,
        )
        nx.draw_networkx_edge_labels(DG, pos, edge_labels=labels, ax=ax)
        ax.figure.canvas.draw()

    def open_random_tab(self):
        i = self.core_tab.count()
        title = f"Test {i}"
        data_tab_widget = DataTab()
        self.update_graph(data_tab_widget.ax, i % len(self.random_tabs))
        self.core_tab.addTab(data_tab_widget, title)
        self.core_tab.setCurrentIndex(i)

    def refresh_all_tabs(self):
        for tab_index in range(self.core_tab.count()):
            data_tab_widget = self.core_tab.widget(tab_index)
            self.update_graph(data_tab_widget.ax, tab_index % len(self.random_tabs))


def main():
    import sys

    app = QApplication([])

    w = SpecWriter()
    w.showMaximized()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

enter image description here

  • Related