嵌入 Qt

嵌入 Qt#

简单的 Qt 应用程序,嵌入 Matplotlib 画布。此程序可以同样适用于任何 Qt 绑定(PyQt6、PySide6、PyQt5、PySide2)。可以通过设置环境变量 QT_API 为绑定名称来选择绑定,或者通过先导入它。

# %matplotlib qt
import sys
import time

import numpy as np

from matplotlib.backends.backend_qtagg import FigureCanvas
from matplotlib.backends.backend_qtagg import \
    NavigationToolbar2QT as NavigationToolbar
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.figure import Figure


class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)
        layout = QtWidgets.QVBoxLayout(self._main)

        static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
        # Ideally one would use self.addToolBar here, but it is slightly
        # incompatible between PyQt6 and other bindings, so we just add the
        # toolbar as a plain widget instead.
        layout.addWidget(NavigationToolbar(static_canvas, self))
        layout.addWidget(static_canvas)

        dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(dynamic_canvas)
        layout.addWidget(NavigationToolbar(dynamic_canvas, self))

        self._static_ax = static_canvas.figure.subplots()
        t = np.linspace(0, 10, 501)
        self._static_ax.plot(t, np.tan(t), ".")

        self._dynamic_ax = dynamic_canvas.figure.subplots()
        t = np.linspace(0, 10, 101)
        # Set up a Line2D.
        self._line, = self._dynamic_ax.plot(t, np.sin(t + time.time()))
        self._timer = dynamic_canvas.new_timer(50)
        self._timer.add_callback(self._update_canvas)
        self._timer.start()

    def _update_canvas(self):
        t = np.linspace(0, 10, 101)
        # Shift the sinusoid as a function of time.
        self._line.set_data(t, np.sin(t + time.time()))
        self._line.figure.canvas.draw()


# if __name__ == "__main__":
#     # Check whether there is already a running QApplication (e.g., if running
#     # from an IDE).
#     qapp = QtWidgets.QApplication.instance()
#     if not qapp:
#         qapp = QtWidgets.QApplication(sys.argv)

#     app = ApplicationWindow()
#     app.show()
#     app.activateWindow()
#     app.raise_()
#     qapp.exec()
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In[1], line 7
      3 import time
      5 import numpy as np
----> 7 from matplotlib.backends.backend_qtagg import FigureCanvas
      8 from matplotlib.backends.backend_qtagg import \
      9     NavigationToolbar2QT as NavigationToolbar
     10 from matplotlib.backends.qt_compat import QtWidgets

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/matplotlib/backends/backend_qtagg.py:9
      5 import ctypes
      7 from matplotlib.transforms import Bbox
----> 9 from .qt_compat import QT_API, QtCore, QtGui
     10 from .backend_agg import FigureCanvasAgg
     11 from .backend_qt import _BackendQT, FigureCanvasQT

File /opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/matplotlib/backends/qt_compat.py:130
    128         break
    129     else:
--> 130         raise ImportError(
    131             "Failed to import any of the following Qt binding modules: {}"
    132             .format(", ".join([QT_API for _, QT_API in _candidates]))
    133         )
    134 else:  # We should not get there.
    135     raise AssertionError(f"Unexpected QT_API: {QT_API}")

ImportError: Failed to import any of the following Qt binding modules: PyQt6, PySide6, PyQt5, PySide2