pyqt 中的多个嵌入式 matplotlib 画布在鼠标悬停时改变大小

Posted

技术标签:

【中文标题】pyqt 中的多个嵌入式 matplotlib 画布在鼠标悬停时改变大小【英文标题】:Multiple embedded matplotlib canvases in pyqt change size on mouse over 【发布时间】:2018-06-05 11:32:11 【问题描述】:

我正在尝试在 PyQt GUI 的多列布局中嵌入多个 matplotlib 图。乍一看,我成功地根据需要设置了布局,但是当将鼠标移到任何画布上时,它们会改变大小并“闪烁”。当按下工具栏上的缩放按钮时,这会变得更加明显。

对于每个 matplotlib 画布,我都连接了一个工具栏。如果我不连接工具栏,则不会出现问题。我尝试过几种方式来排列工具栏和画布 - 使用 QGridLayout 或嵌套的 QVBoxLayouts 和 QHBoxLayouts。无论哪种方式,如果有并排的地块,就会出现问题。如果我将所有图都放在一列中,则不会。

我已经在 Windows(Anaconda 5.0.1)的 Python 3.6 和 Linux(KDE Neon 64 位)中的 PyQt4 和 Python 3.5.2 以及 PyQt4 和 PyQt5(v. 5.7.1)、matplotlib 1.5 中尝试过这个。 1 但结果相同。我也尝试过使用 add_axes 而不是 add_subplot。有人可以帮助我了解导致此问题的原因或找到某种解决方法吗?我不能使用 matplotlib 子图。

from PyQt5 import QtCore, QtGui, QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()

        figure1 = Figure()
        figure2 = Figure()
        figure3 = Figure()
        figure4 = Figure()
        canvas1 = FigureCanvas(figure1)
        canvas2 = FigureCanvas(figure2)
        canvas3 = FigureCanvas(figure3)
        canvas4 = FigureCanvas(figure4)
        ax1 = figure1.add_subplot(111)
        ax2 = figure2.add_subplot(111)
        ax3 = figure3.add_subplot(111)
        ax4 = figure4.add_subplot(111)

        toolbar1 = NavigationToolbar(canvas1, self)
        toolbar2 = NavigationToolbar(canvas2, self)
        toolbar3 = NavigationToolbar(canvas3, self)
        toolbar4 = NavigationToolbar(canvas4, self)

        mainLayout = QtWidgets.QGridLayout()
        mainLayout.addWidget(toolbar1,0,0)
        mainLayout.addWidget(toolbar2,0,1)
        mainLayout.addWidget(toolbar3,2,0)
        mainLayout.addWidget(toolbar4,2,1)
        mainLayout.addWidget(canvas1,1,0)
        mainLayout.addWidget(canvas2,1,1)
        mainLayout.addWidget(canvas3,3,0)
        mainLayout.addWidget(canvas4,3,1)

        self.setLayout(mainLayout)
        self.setWindowTitle("Flow Layout")

if __name__ == '__main__':

    import sys

    app = QtWidgets.QApplication(sys.argv)
    mainWin = Window()
    mainWin.show()
    sys.exit(app.exec_())

【问题讨论】:

我在 windows 8.1 上使用 pyqt4 和 matplotlib 2.1。对我来说,情节看起来和感觉都很好;我观察不到任何闪烁。重现不良行为的具体步骤是什么?您究竟观察到了什么? 将鼠标悬停在绘图区域上,画布的宽度会发生变化。在扫过两个/所有地块后,宽度会稳定下来。现在我相信我明白了其中的原因。当窗口初始化时,每个画布/工具栏都被赋予一个默认大小,导致每列的大小为 50%。但是在鼠标悬停时,工具栏会显示显示坐标,这需要更多空间 - 因此会改变宽度。我更愿意确保每列都获得 50% 的空间,但我还没有弄清楚如何做到这一点。现在我将窗口初始化得很宽 我现在在 Gentoo Linux(32 位)上使用 matplotlib-1.4.3、pyqt-5.7.1 和 python-3.4.5 尝试了您的代码,但我看不到您报告的问题。 我有更新或类似的版本。我会用版本更新我的问题 【参考方案1】:

我遇到了类似的问题,我通过以下方式解决了它:

toolbar1.setMinimumWidth(canvas1.width())
toolbar2.setMinimumWidth(canvas2.width())
toolbar3.setMinimumWidth(canvas3.width())
toolbar4.setMinimumWidth(canvas4.width())

问题是当工具栏变得比画布更宽时。

【讨论】:

如果没有调整窗口大小,这确实有效。但是,如果我将窗口宽度增加到例如大约 125%,然后将其降低到大约 110%,然后问题再次出现。当画布改变大小时,需要更新最小宽度。我已经尝试将 self.resizeEvent 连接到包含上述行的方法,但由于它是设置的 minimumSize 这可以防止再次缩小窗口:-/

以上是关于pyqt 中的多个嵌入式 matplotlib 画布在鼠标悬停时改变大小的主要内容,如果未能解决你的问题,请参考以下文章

matplotlib pyqt5画布上两个可拖动点之间的线

为啥我不能在 pyqt5 gui 中嵌入的 matplotlib 颜色图中成功绘制感兴趣区域?

急急急 pyqt5 matplotlib 多线程问题,求大佬指点啊

在 PyQt4 的嵌入式 matplotlib 图中使用 ginput

Anaconda3使用matplotlib画图报错问题的解决方法

将 Matplotlib 图形嵌入到小部件中 - PyQt5