【问题标题】:How to hide or delete NavigationToolbar from MainWindow如何从 MainWindow 隐藏或删除 NavigationToolbar
【发布时间】:2021-02-16 09:09:32
【问题描述】:

基本上,每次选中复选框时,我都会尝试用一组新图标重绘我的NavigationToolbar。我将NavigationToolbar2QT 子类化为Toolbar_route,它在应用启动时运行良好,但更新无法正常运行。

编辑:

我还是想不通,所以我做了一个小应用程序来说明它,这是我的结构:

????myApp
 ┣ ????resources
 ┃ ┣ ????images_dark
 ┃ ┃ ┗ ????matplotlib-dark-images
 ┃ ┃ ┃ ┣ ????<...>.png
 ┃ ┗ ????GUI_preferences.ini
 ┣ ????custom_mpl_toolbar.py
 ┣ ????myApp_GUI_pref.py
 ┣ ????myApp_main.py
 ┗ ????save_restore.py

我猜问题是一样的,我没有正确摆脱 window_plot_update 中的旧画布和工具栏。这是myApp_main.py

import os
import random

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.pyplot import rcParams, style
from PyQt5 import QtCore
from PyQt5 import QtWidgets as qtw
from PyQt5.QtWidgets import QMainWindow, QSizePolicy, QWidget

# cwd modules
from custom_mpl_toolbar import MyMplToolbar
from myApp_GUI_pref import Ui_Form
from save_restore import guirestore, guisave


class NewWindow(QMainWindow):
    """MainWindow factory"""
    def __init__(self):
        super().__init__()
        global window_list
        window_list = []  # Allow multiple MainWindow instances
        # ? Preferences on program start
        BASEDIR = os.path.dirname(__file__)
        GUI_preferences_path = os.path.join(BASEDIR, 'resources/GUI_preferences.ini')
        self.GUI_preferences = QtCore.QSettings(GUI_preferences_path, QtCore.QSettings.IniFormat)
        self.add_new_window()

    def add_new_window(self):
        """Create now MainWindow instance"""
        window = MainWindow(self, self.GUI_preferences)
        window_list.append(window)
        window.show()


class MainWindow(QMainWindow):
    def __init__(self, window, GUI):
        super().__init__()
        self.window = window
        self.GUI_preferences = GUI
        self.instances_route_canvas = []
        self.instances_route_toolbar = []

        self.centralwidget = qtw.QWidget()
        self.centralwidget.setMaximumSize(QtCore.QSize(833, 559))
        self.centralwidget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = qtw.QVBoxLayout(self.centralwidget)
        self.setCentralWidget(self.centralwidget)

        self.menubar = qtw.QMenuBar()
        self.menubar.setGeometry(QtCore.QRect(0, 0, 819, 21))
        self.menubar.setObjectName("menubar")
        self.menuFile = qtw.QMenu(self.menubar)
        self.menuFile.setObjectName("File")
        self.setMenuBar(self.menubar)
        menu_new = self.menubar.addMenu("File")

        self.actionNew_Window = qtw.QAction()
        menu_new.addAction('New window', self.window.add_new_window)
        self.actionEdit = qtw.QAction()
        menu_new.addAction('Preferences', self.show_preferences)
        self.mainEdits()

    def mainEdits(self):
        """MainWindow GUI changes"""
        # ? window exit
        qtw.QAction("Quit", self).triggered.connect(self.closeEvent)

        #? Instantiate and restore theme preferences
        self.pref_screen = Preferences(self.GUI_preferences)

        #? Embedded matplotlib in Route tab
        self.route_canvas = PlotCanvas_route(self.GUI_preferences)
        darkMode = bool(int(self.GUI_preferences.value('cb_dark')))
        self.route_toolbar = Toolbar_route(
            self.route_canvas, None, coordinates=True, darkMode=darkMode
        )  # Do not set parent on this first widget - Prevents toolbar theme update
        self.verticalLayout.addWidget(self.route_canvas)
        self.verticalLayout.addWidget(self.route_toolbar)

        # ? Keep track of NavToolbar and Canvas
        self.instances_route_canvas.append(self.route_canvas)
        self.instances_route_toolbar.append(self.route_toolbar)

    def show_preferences(self):
        """Shows the Preferences widget"""
        guirestore(self.pref_screen, self.GUI_preferences)
        self.pref_screen.setWindowModality(QtCore.Qt.ApplicationModal)
        self.pref_screen.setFocus(True)
        self.pref_screen.show()

    def closeEvent(self, event):
        """Close current window"""
        close = qtw.QMessageBox(qtw.QMessageBox.Question, 'Exit', 'Exit application?', parent=self)
        close_reject = close.addButton('No', qtw.QMessageBox.NoRole)
        close_accept = close.addButton('Yes', qtw.QMessageBox.AcceptRole)
        close.exec()  # Necessary for property-based API
        if close.clickedButton() == close_accept:
            event.accept()
        else:
            event.ignore()


class Toolbar_route(MyMplToolbar):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class PlotCanvas_route(FigureCanvas):
    """Route input data graph"""
    def __init__(self, GUI, dpi=100):
        # TODO param font lost on new window and updates
        self.GUI_preferences = GUI
        self.route_fig = Figure(dpi=dpi)
        FigureCanvas.__init__(self, self.route_fig)
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.plot()

    def plot(self):
        """Clear and plot chart"""
        self.route_fig.clear()  # clear wrong format on graph init
        self.dark_mode_set = bool(int(self.GUI_preferences.value('cb_dark')))
        if self.dark_mode_set:
            self.route_fig.patch.set_facecolor(
                (0.09803921569, 0.13725490196, 0.17647058824)
            )  # light grey
            rcParams['axes.facecolor'] = (0.19607843137, 0.25490196078, 0.29411764706)  # dark grey
            rcParams['text.color'] = rcParams['axes.labelcolor'] = rcParams[
                'axes.edgecolor'] = rcParams['xtick.color'] = rcParams['ytick.color'] = 'white'
            rcParams['savefig.facecolor'] = (0.19607843137, 0.25490196078, 0.29411764706)
        else:
            style.use('default')
            self.route_fig.patch.set_facecolor('white')
        rcParams['savefig.dpi'] = 300
        rcParams['font.family'] = 'Euclid'

        data = [random.random() for i in range(50)]
        self.ax = self.figure.add_subplot(111)
        self.line0, = self.ax.plot(data, 'r-', linewidth=0.5)
        self.ax.set_title('Very nice graph')
        # Line color has to be set during/after axis plot
        if self.dark_mode_set: self.line0.set_color("white")
        try:
            watermarkText = Preferences.watermarkText
        except:
            watermarkText = str((self.GUI_preferences.value('watermark')))
        self.route_fig.text(
            0.5, 0.5, watermarkText, fontsize=20, color='gray', ha='center', va='center', alpha=0.5
        )
        self.draw()


class Preferences(QWidget, Ui_Form):
    """Preferences widget screen"""
    def __init__(self, GUI):
        super().__init__()
        self.setupUi(self)
        self.GUI_preferences = GUI
        try:
            guirestore(self, self.GUI_preferences)
        except:  # Create new empty file if none found
            guisave(self, self.GUI_preferences)
        self.watermarkText = self.watermark.text()
        self.pushButton.clicked.connect(self.hide)
        self.cb_dark.stateChanged.connect(self.cb_dark_check)
        self.cb_watermark.stateChanged.connect(self.cb_watermark_check)
        self.cb_dark_check()  # Restores dark mode on start

    def cb_dark_check(self):
        """Define stylesheet based on saved settings"""
        # * Save checkbox status after signal
        guisave(self, self.GUI_preferences)
        self.dark_mode_set = bool(int(self.GUI_preferences.value('cb_dark')))
        # * Apply corresponding style
        self.window_plot_update()
        try:
            import qdarkstyle
            if not self.dark_mode_set:
                app.setStyleSheet("")  # Default style
            else:
                app.setStyleSheet(qdarkstyle.load_stylesheet())
            # * Update icons, toolbar and canvas

        except:
            qtw.QMessageBox.critical(self, "Error", "Could not set all stylesheet settings.")

    # ! Currently not updating multiple graphs without app restart
    def cb_watermark_check(self):
        """Define watermark based on checkbox state and line text"""
        if self.cb_watermark.isChecked():
            self.watermarkText = self.watermark.text()
        else:
            self.watermarkText = ""
        # Replot with set watermarkText
        for window in window_list:
            window.route_canvas.plot()
        guisave(self, self.GUI_preferences)

    def window_plot_update(self):
        """Update icons and replot"""
        for window in window_list:
            window.route_toolbar = Toolbar_route(
                window.route_canvas, None, coordinates=True, darkMode=self.dark_mode_set
            )
            window.route_canvas = PlotCanvas_route(window.GUI_preferences)

            window.instances_route_canvas.append(window.route_canvas)
            window.instances_route_toolbar.append(window.route_toolbar)
            # ? Hide or delete previous
            if len(window.instances_route_toolbar) > 1:
                a = window.instances_route_toolbar[-1]
                a.setVisible(False)
                a = window.instances_route_canvas[-1]
                a.setVisible(False)


if __name__ == "__main__":
    import sys
    app = qtw.QApplication(sys.argv)
    w = NewWindow()  # Instantiate window factory class

    # ? Exit with Ctrl + C
    timer = QtCore.QTimer()
    timer.timeout.connect(lambda: None)
    timer.start(100)

    sys.exit(app.exec_())

如果需要,除了图标之外的其余文件都在this gist 中。

【问题讨论】:

标签: python-3.x matplotlib pyqt pyqt5


【解决方案1】:

通过以下方式解决了这个问题,现在在使用设置的主题更新后只显示一个工具栏和图表:

def window_plot_update(self):
    """Update icons and replot"""
    for window in window_list:
        window.route_canvas = PlotCanvas_route(window.GUI_preferences)
        darkMode = bool(int(window.GUI_preferences.value('cb_dark')))
        window.route_toolbar = Toolbar_route(
            window.route_canvas, None, coordinates=True, darkMode=darkMode
        ) 
        window.verticalLayout.addWidget(window.route_canvas)
        window.verticalLayout.addWidget(window.route_toolbar)
        window.instances_route_canvas.append(window.route_canvas)
        window.instances_route_toolbar.append(window.route_toolbar)
        if len(window.instances_route_toolbar) > 1:
            window.instances_route_canvas[0].hide()
            window.instances_route_toolbar[0].hide()
            del window.instances_route_canvas[0]
            del window.instances_route_toolbar[0]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 2020-08-18
    • 2013-06-29
    • 2022-05-01
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多