Как открыть полноэкранный график matplotlib? - PullRequest
0 голосов
/ 28 марта 2020

Я работаю над приложением pyqt5, и есть виджет, содержащий график, созданный с помощью matplotlib. Я хочу добавить функцию, которая позволяет пользователю нажимать на график, и он будет открыт во весь экран. Как я могу это сделать?
График в виджете построен так:

class CanvasUp(FigureCanvas):
    def __init__(self, parent=None, width=5, height=5, dpi=50):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        self.plot()

def plot(self):
            # obtaining data
            ...
            ax = self.figure.add_subplot(111)

            self.figure.text(0.5, 0.5, "TEST", transform=ax.transAxes,
                             fontsize=40, color='gray', alpha=0.5,
                             ha='center', va='center')
            ax.fill_between(x1, y1=y1, label='psavert', alpha=0.5, color='tab:green', linewidth=2)

            dt = ax.plot(x1, y1)
            ax.set_title(lab, loc='left')
            ax.grid()
            self.draw_idle()           

Если я упросту мою программу, она будет выглядеть так:


from PyQt5.QtWidgets import QDialog, QVBoxLayout
from PyQt5.QtWidgets import QApplication
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import sys

class CanvasUp(FigureCanvas):
    def __init__(self, parent=None, width=5, height=5, dpi=50):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        self.plot()

    def plot(self):
        try:
            x1 = [1, 2, 3]
            y1 = [3, 2, 1]
            ax = self.figure.add_subplot(111)
            ax.set_ylim([0, max(y1)*1.15])

            self.figure.text(0.5, 0.5, "test", transform=ax.transAxes,
                             fontsize=40, color='gray', alpha=0.5,
                             ha='center', va='center')
            ax.fill_between(x1, y1=y1, label='psavert', alpha=0.5, color='tab:green', linewidth=2)
            dt = ax.plot(x1, y1)
            ax.grid()
            self.draw_idle()
        except:
            print("Bad graphs")


class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.setGeometry(50, 50, 700, 700)
        layout = QVBoxLayout(self)
        plot = CanvasUp()
        layout.addWidget(plot)
        self.show()

if __name__ == '__main__':
        App = QApplication(sys.argv)
        window = MainWindow()
        sys.exit(App.exec())

1 Ответ

1 голос
/ 28 марта 2020

Если вы хотите отобразить дочерний виджет в полноэкранном режиме, вам нужно установить для его родителя значение None.

Обратите внимание, что если вы хотите восстановить предыдущее состояние Вы также должны отслеживать предыдущую позицию в макете. В вашем примере это не является обязательным требованием, но если есть больше виджетов, вы должны учесть это.

class CanvasUp(FigureCanvas):
    toggle = pyqtSignal()
    def __init__(self, parent=None, width=5, height=5, dpi=50):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)
        self.plot()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            # emit a signal to notify the parent that we want to toggle the mode
            self.toggle.emit()

    # ...

class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.setGeometry(50, 50, 700, 700)
        self.setWindowTitle('fig test')
        layout = QVBoxLayout(self)
        self.plot = CanvasUp()
        layout.addWidget(self.plot)
        self.show()
        self.plot.toggle.connect(self.toggleFigure)

    def toggleFigure(self):
        if self.plot.parent():
            # store the current index in the layout
            self.layoutIndex = self.layout().indexOf(self.plot)
            self.plot.setParent(None)
            # manually reparenting a widget requires to explicitly show it,
            # usually by calling show() or setVisible(True), but this is
            # automatically done when calling showFullScreen()
            self.plot.showFullScreen()
        else:
            self.layout().insertWidget(self.layoutIndex, self.plot)

Если вы используете макет сетки, то индекса недостаточно, так как insertWidget существует только для QBoxLayouts, поэтому координаты сетки должны быть извлечены до повторного создания виджета.
Учтите, что, хотя вы могли бы сохранить координаты в переменной при добавлении виджета в макет, всегда лучше получить их только при необходимости.

class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.setGeometry(50, 50, 700, 700)
        self.setWindowTitle('fig test')
        layout = QGridLayout(self)
        layout.addWidget(QPushButton(), 0, 0)
        layout.addWidget(QPushButton(), 0, 1)
        self.plot = CanvasUp()
        layout.addWidget(self.plot, 1, 0, 1, 2)
        self.show()
        self.plot.toggle.connect(self.toggleFigure)

    def toggleFigure(self):
        if self.plot.parent():
            layoutIndex = self.layout().indexOf(self.plot)
            # store the position in grid coordinates:
            # row, column, horizontal span and vertical span
            self.layoutPosition = self.layout().getItemPosition(layoutIndex)
            self.plot.setParent(None)
            self.plot.showFullScreen()
        else:
            self.layout().addWidget(self.plot, *self.layoutPosition)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...