在 wxpython GUI 中嵌入 matplotlib 图的大小调整问题

sizing problems embedding matplotlib figure in wxpython GUI

我有一些生成绘图的代码。这段代码是使用 pylab 的交互模式编写的,但此时我需要重新编写代码,以便将绘图嵌入到我的 wxPython GUI 中。问题是,该图被压缩成一个我似乎无法更改的小默认尺寸。框架可以手动调整大小,然后一切看起来都不错。

这是一个演示基本问题的简单示例:

import wx
import matplotlib
import matplotlib.pyplot as plt
import numpy as np


class CanvasPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.figure = self.fake_depthplot()                                                               
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.SetSizer(self.sizer)
        self.Fit()
        # these print statements give me a number like (1600, 1600)
        # however, when I use the wxpython inspector, it shows that the actual display size is MUCH smaller
        print self.Size 
        print self.canvas.Size

    def fake_depthplot(self):
        main_plot = plt.figure(1, figsize=(10, 8))
        main_plot.add_axes([0, 0, 1, 1])

        x1 = np.linspace(0.0, 5.0)
        x2 = np.linspace(0.0, 2.0)

        y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
        y2 = np.cos(2 * np.pi * x2)

        plt.subplot(4, 2, 1)
        plt.plot(x1, y1, 'ko-')
        plt.title('A tale of 2 subplots')
        plt.ylabel('Damped oscillation')

        plt.subplot(2, 1, 2)
        plt.plot(x2, y2, 'r.-')
        plt.xlabel('time (s)')
        plt.ylabel('Undamped')

        return main_plot


if __name__ == "__main__":
    app = wx.PySimpleApp()
    fr = wx.Frame(None, title='test')
    panel = CanvasPanel(fr)                                                                                                         
    if '-i' in sys.argv:
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
    fr.Show()
    app.MainLoop()

我希望相框可以比现在大一倍。此外,当我 运行 这段代码时,显示似乎变大了,但随后又调整为默认大小,我不喜欢很快。我猜这有一个简单的解决方案,但我似乎找不到。 None 我为其他问题找到的答案解决了我的问题。

我认为建议不要使用 pyplot。对于 wxPython,我也喜欢使用 sized_controls,它隐藏了一些 sizer 的东西,但如果你需要它仍然可以让你控制,同时它们符合平台 UI 指南。

使用 sizer 时,当你添加一些东西时,你需要告诉容器调用 Layout/Fit 来告诉它自己调整到新的 children。

您可能还想查看 mpl 示例: http://matplotlib.org/examples/user_interfaces/index.html

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import wx.lib.sized_controls as sc

import matplotlib as mpl
mpl.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas

import numpy as np


class CanvasPanel(sc.SizedPanel):
    def __init__(self, parent):
        super(CanvasPanel, self).__init__(parent)
        self.figure = mpl.figure.Figure(figsize=(10, 8), dpi=75,
                                        facecolor='white', edgecolor='white')

        self.fake_depthplot()                                                               
        self.canvas = FigureCanvas(self, -1, self.figure)

        # these print statements give me a number like (1600, 1600)
        # however, when I use the wxpython inspector, it shows that the actual display size is MUCH smaller
        print(self.Size)
        print(self.canvas.Size)

    def fake_depthplot(self):
        main_plot = self.figure
        main_plot.add_axes([0, 0, 1, 1])

        x1 = np.linspace(0.0, 5.0)
        x2 = np.linspace(0.0, 2.0)

        y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
        y2 = np.cos(2 * np.pi * x2)

        plt = main_plot.add_subplot(4, 2, 1)
        plt.plot(x1, y1, 'ko-')
        plt.title.set_text('A tale of 2 subplots')
        plt.set_ylabel('Damped oscillation')

        plt = main_plot.add_subplot(2, 1, 2)
        plt.plot(x2, y2, 'r.-')
        plt.set_xlabel('time (s)')
        plt.set_ylabel('Undamped')


if __name__ == "__main__":
    app = wx.App()
    fr = sc.SizedFrame(None, title='test')
    print(fr.Size)
    pane = fr.GetContentsPane()
    panel = CanvasPanel(pane)
    fr.Fit()
    import sys
    if '-i' in sys.argv:
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
    fr.Show()
    app.MainLoop()