0

I am trying to plot multiple graphs in a pyqt5 window widget. I was able to do that but the size of the figure would just be "compressed" if I add more graphs to the window. See the comparison by running below code and clicking Push for Window 1 vs Push for Window 2.

I wanted to add a scrollbar to the canvas, so that I can preserve the size of the graphs, just like putting multiple graphs in a word file and use the scrollbar to move up and down to review the graphs. How should I do that?

import sys
import pandas as pd
import numpy as np

from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QWidget,
)

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt

class AnotherWindow1(QWidget):


    def __init__(self):
        super().__init__()
        self.figure = plt.figure(figsize=(45,15))    
        self.canvas = FigureCanvas(self.figure)  
        layout = QVBoxLayout()
        button1 = QPushButton("Plot")
        button1.clicked.connect(self.plot)
        button2 = QPushButton("Back")
        button2.clicked.connect(self.close_window)
        layout.addWidget(button1)
        layout.addWidget(button2)
        layout.addWidget(self.canvas)
        self.setLayout(layout)

    def close_window(self):
        self.close()

    def plot(self):
        self.figure.clear()
        ax1 =  self.figure.add_subplot(111) 
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax1)
        self.canvas.draw()

class AnotherWindow2(QWidget):


    def __init__(self):
        super().__init__()
        self.figure = plt.figure(figsize=(45,15))    
        self.canvas = FigureCanvas(self.figure)  
        self.canvas2 = FigureCanvas(self.figure) 
        self.canvas3 = FigureCanvas(self.figure)  
        layout = QVBoxLayout()
        button1 = QPushButton("Plot")
        button1.clicked.connect(self.plot)
        button2 = QPushButton("Back")
        button2.clicked.connect(self.close_window)
        layout.addWidget(button1)
        layout.addWidget(button2)
        layout.addWidget(self.canvas)
        layout.addWidget(self.canvas2)
        layout.addWidget(self.canvas3)
        self.setLayout(layout)

    def close_window(self):
        self.close()

    def plot(self):
        self.figure.clear()
        ax1 =  self.figure.add_subplot(111) 
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax1)
        self.canvas.draw()
        ax2 =  self.figure.add_subplot(111) 
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax2)
        self.canvas2.draw()
        ax2 =  self.figure.add_subplot(111) 
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax2)
        self.canvas3.draw()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.window1 = AnotherWindow1()
        self.window2 = AnotherWindow2()

        l = QVBoxLayout()
        button1 = QPushButton("Push for Window 1")
        button1.clicked.connect(self.show_window1)
        l.addWidget(button1)

        button2 = QPushButton("Push for Window 2")
        button2.clicked.connect(self.show_window2)
        l.addWidget(button2)

        w = QWidget()
        w.setLayout(l)
        self.setCentralWidget(w)

    def show_window1(self):
        self.window1.show()

    def show_window2(self):
        self.window2.show()


app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()

1 Answer 1

1

You have to use a QScrollArea that contains a QWidget as a container for the canvas

import sys
import pandas as pd
import numpy as np

from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QMainWindow,
    QPushButton,
    QScrollArea,
    QVBoxLayout,
    QWidget,
)

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


class AnotherWindow1(QWidget):
    def __init__(self):
        super().__init__()

        self.figure = Figure(figsize=(45, 15))
        self.canvas = FigureCanvas(self.figure)

        button1 = QPushButton("Plot")
        button1.clicked.connect(self.plot)
        button2 = QPushButton("Back")
        button2.clicked.connect(self.close_window)

        layout = QVBoxLayout(self)
        layout.addWidget(button1)
        layout.addWidget(button2)
        layout.addWidget(self.canvas)

    def close_window(self):
        self.close()

    def plot(self):
        self.figure.clear()
        ax1 = self.figure.add_subplot(111)
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax1)
        self.canvas.draw()


class AnotherWindow2(QWidget):
    def __init__(self):
        super().__init__()
        self.figure = Figure(figsize=(45, 15))

        self.canvas = FigureCanvas(self.figure)
        self.canvas.setMinimumSize(640, 480)
        self.canvas2 = FigureCanvas(self.figure)
        self.canvas2.setMinimumSize(640, 480)
        self.canvas3 = FigureCanvas(self.figure)
        self.canvas3.setMinimumSize(640, 480)

        canvas_scrollarea = QScrollArea(widgetResizable=True)
        canvas_container = QWidget()
        canvas_scrollarea.setWidget(canvas_container)
        canvas_layout = QVBoxLayout(canvas_container)
        canvas_layout.addWidget(self.canvas)
        canvas_layout.addWidget(self.canvas2)
        canvas_layout.addWidget(self.canvas3)

        button1 = QPushButton("Plot")
        button1.clicked.connect(self.plot)
        button2 = QPushButton("Back")
        button2.clicked.connect(self.close_window)

        layout = QVBoxLayout(self)

        layout.addWidget(button1)
        layout.addWidget(button2)
        layout.addWidget(canvas_scrollarea)

    def close_window(self):
        self.close()

    def plot(self):
        self.figure.clear()
        ax1 = self.figure.add_subplot(111)
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax1)
        self.canvas.draw()
        ax2 = self.figure.add_subplot(111)
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax2)
        self.canvas2.draw()
        ax2 = self.figure.add_subplot(111)
        data = pd.DataFrame(np.random.rand(5))
        data.plot(ax=ax2)
        self.canvas3.draw()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.window1 = AnotherWindow1()
        self.window2 = AnotherWindow2()

        button1 = QPushButton("Push for Window 1")
        button1.clicked.connect(self.show_window1)

        button2 = QPushButton("Push for Window 2")
        button2.clicked.connect(self.show_window2)

        w = QWidget()
        l = QVBoxLayout(w)
        l.addWidget(button1)
        l.addWidget(button2)
        self.setCentralWidget(w)

    def show_window1(self):
        self.window1.show()

    def show_window2(self):
        self.window2.show()


app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I think this is a very informative and effective answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.