1

I want to plot a data-frame in one of the tabs of my application. I'm using python 3.6.9 and PyQt5.
I implemented a TabWidget from another answer. In one of those tabs I used MplCanvas from Plotting with Matplotlib to plot a data from my data-frame. Needed classes:

class TabWidget(QtWidgets.QTabWidget):
    def __init__(self, *args, **kwargs):
        QtWidgets.QTabWidget.__init__(self, *args, **kwargs)
        self.setTabBar(TabBar(self))
        self.setTabPosition(QtWidgets.QTabWidget.West)


class MplCanvas(FigureCanvasQTAgg):

    def __init__(self, parent=None, width=6.4, height=4.8, dpi=394):
        fig = Figure(figsize= (width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)


class TabBar(QtWidgets.QTabBar):
    def tabSizeHint(self, index):
        s = QtWidgets.QTabBar.tabSizeHint(self, index)
        s.transpose()
        return s

    def paintEvent(self, event):
        painter = QtWidgets.QStylePainter(self)
        opt = QtWidgets.QStyleOptionTab()

        for i in range(self.count()):
            self.initStyleOption(opt, i)
            painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, opt)
            painter.save()

            s = opt.rect.size()
            s.transpose()
            r = QtCore.QRect(QtCore.QPoint(), s)
            r.moveCenter(opt.rect.center())
            opt.rect = r

            c = self.tabRect(i).center()
            painter.translate(c)
            painter.rotate(90)
            painter.translate(-c)
            painter.drawControl(QtWidgets.QStyle.CE_TabBarTabLabel, opt)
            painter.restore()

The QMainWindow of application:

class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.title = 'PLOT APP'
        self.left = 0
        self.top = 0
        self.width = 1024
        self.height = 600
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.tab_widget = MyTabWidget(self, self.width, self.height)
        self.setCentralWidget(self.tab_widget)
        self.show()

And to run the application:

app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())

And the MyTabWidget class in which I implemented my code:

class MyTabWidget(QWidget):

    def __init__(self, parent, width, height):
        super(QWidget, self).__init__(parent)
        self.layout = QVBoxLayout(self)

        # creating a tab bar
        self.tab = TabWidget()

        self.new_df = self.prepare_data()

        self.layout_gauges = QHBoxLayout(self)

        self.layout_plot = QVBoxLayout(self)

        self.canvas = MplCanvas(self, width=10, height=8, dpi=100)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.comboBox = QtWidgets.QComboBox(self)

        # widgets associated with tab
        self.graphs_tab = QWidget()

        # assigning tab to tab-bar
        self.tab.addTab(self.graphs_tab, "Graphs")


        # graphs tab
        self.graphs_tab.layout = QVBoxLayout(self)

        self.layout_combobox_time_filter = QHBoxLayout(self)
        self.layout_combobox = QHBoxLayout(self)

        self.draw_graphs()
        self.graphs_tab.setLayout(self.graphs_tab.layout)

        self.layout.addWidget(self.tab)
        self.setLayout(self.layout)

        self.tab.resize(300, self.ertefa)
        self.tab.show()

        def draw_graphs(self):

            for item in self.new_df.columns[1:]:
                self.comboBox.addItem(str(item))
            self.comboBox.setMaximumWidth(200)

            self.comboBox.activated[str].connect(self.draw_plot)

            self.layout_combobox.addWidget(self.comboBox)
            self.layout_combobox.setAlignment(QtCore.Qt.AlignRight)
            self.layout_combobox_time_filter.addLayout(self.layout_combobox.layout())

            self.canvas.axes.plot(self.new_df.index, self.new_df.loc[:, self.comboBox.currentText()])
            self.label = self.canvas.axes.set_xlabel('Time', fontsize=9)
            self.label = self.canvas.axes.set_ylabel(self.comboBox.currentText(), fontsize=9)
            self.canvas.axes.legend(str(self.comboBox.currentText()))
            self.canvas.draw()

            self.graphs_tab.layout.addWidget(self.toolbar)
            self.graphs_tab.layout.addWidget(self.canvas)
            self.graphs_tab.layout.addLayout(self.layout_combobox_time_filter.layout())

    def draw_plot(self):

        self.canvas.axes.plot(self.new_df.index, self.new_df.loc[:, self.comboBox.currentText()])
        self.label = self.canvas.axes.set_xlabel('Time', fontsize=9)
        self.label = self.canvas.axes.set_ylabel(self.comboBox.currentText(), fontsize=9)
        self.canvas.axes.legend(self.comboBox.currentText())
        self.canvas.draw()

    def prepare_data(self):
        # extract data from file
        sensor = pd.read_excel("file.xlsx")
        return  df_new

The default values for width and height are (width=6.4, height=4.8) based on documentation.

My screen size is 1024 * 600 pixel. Then I create an instance of this class as follows and assign a NavigationToolbar to it:

self.canvas = MplCanvas(self, width=10, height=7, dpi=100)
self.toolbar = NavigationToolbar(self.canvas, self)

I plot my data-frame as following:

self.canvas.axes.plot(self.new_df.index, self.new_df.loc[:, self.comboBox.currentText()])
self.label = self.canvas.axes.set_xlabel('Time', fontsize=9)
self.label = self.canvas.axes.set_ylabel(self.comboBox.currentText(), fontsize=9)
self.canvas.axes.legend(str(self.comboBox.currentText()))
self.canvas.draw()

but every time I change the width and height of the canvas its dimensions don't change. What is wrong with my code or my understanding of this?

enter image description here

And the legend of the plot isn't completely displayed, as the picture indicates, only the first character of the legend is shown. How to fix it?


Ok, I found the problem. in MplCanvas where the fig object is initialized, tight_layout property should be set to True.

class MplCanvas(FigureCanvasQTAgg):

def __init__(self, parent=None, width=6.4, height=4.8, dpi=394):
    fig = Figure(figsize= (width, height), dpi=dpi, tight_layout=True)
    self.axes = fig.add_subplot(111)
    super(MplCanvas, self).__init__(fig)

But the legend is shown with one character only.

Shahriar.M
  • 818
  • 1
  • 11
  • 24

0 Answers0