Matplotlib NavigationToolbar 重叠图(在 PyQt4 嵌入中)

Matplotlib NavigationToolbar overlapping plot (within PyQt4 embedding)

我有一个 PyQt window,它需要同时具有绘图和导航工具栏。但是,我似乎无法让这两个对象啮合在一起;即,工具栏位于图的顶部,扩展相同的水平长度,适当缩放且不重叠。以下是我的最小工作示例。非常感谢您的观看!

import sys, os

from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import random

class App(QtGui.QMainWindow):

    def __init__(self):
        super(App, self).__init__()
        self.left = 10
        self.top = 10
        self.title = 'Minimum, working example'
        self.width = 640
        self.height = 400
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        m = PlotCanvas(self, width=5, height=4)
        m.move(0,0)
        self.show()


class PlotCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.updateGeometry(self)

        ##########################
        #trouble seems to be here:
        fig.set_tight_layout(True)
        self.canvas = FigureCanvas(fig)
        self.toolbar = NavigationToolbar(self.canvas, self)
        ##########################

        self.plot()


    def plot(self):
        data = [random.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-')
        ax.set_title("Is this getting overlapped by the toolbar?")
        self.draw()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

当您使用 self.canvas = FigureCanvas (fig) 时,您正在创建另一个 FigureCanvas为什么要创建另一个?,没有必要。

为什么重叠了?

子部件的位置是相对于父部件的,在本例中它是 self.toolbar 是 self.canvas 的子部件,所以 self.toolbar 将在 self.canvas.

为了处理小部件的位置和大小,Qt 提供了布局,在这种情况下是必要的。另一方面,工具栏不需要位于 PlotCanvas class 内部。最后,当使用 QMainWindow 时,您不应直接放置小部件,因为它具有自定义布局,因此您必须创建一个中央小部件。

import sys, os

from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import random

class App(QtGui.QMainWindow):
    def __init__(self):
        super(App, self).__init__()
        self.left = 10
        self.top = 10
        self.title = 'Minimum, working example'
        self.width = 640
        self.height = 400
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        centralwidget = QtGui.QWidget()
        self.setCentralWidget(centralwidget)
        m = PlotCanvas(self, width=5, height=4)
        toolbar =  NavigationToolbar(m, self)
        vbl = QtGui.QVBoxLayout(centralwidget)
        vbl.addWidget(toolbar)
        vbl.addWidget(m)
        self.show()


class PlotCanvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        self.updateGeometry()
        fig.set_tight_layout(True)
        self.plot()

    def plot(self):
        data = [random.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-')
        ax.set_title("Is this getting overlapped by the toolbar?")
        self.draw()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())