简体   繁体   English

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

[英]sizing problems embedding matplotlib figure in wxpython GUI

I have some code that generates a plot. 我有一些生成图的代码。 This code was written using pylab's interactive mode, but at this point I need to re-write the code so that I can embed the plot into my wxPython GUI. 这段代码是使用pylab的交互模式编写的,但是在这一点上,我需要重新编写代码,以便可以将绘图嵌入到wxPython GUI中。 The problem is, the figure shows up squished down into a small default size that I can't seem to change. 问题是,该图显示被压缩为一个很小的默认大小,我似乎无法更改。 The frame can be manually resized and then everything looks good. 可以手动调整框架的大小,然后一切看起来不错。

Here is a simple example that demonstrates the basic problem: 这是一个简单的示例,演示了基本问题:

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()

I'd like for the frame to be maybe twice as large as it is currently. 我希望该框架的大小可能是当前框架的两倍。 Also, when I run this code, the display seems to flash into existence as larger, but then it resizes to the default I don't like very quickly. 另外,当我运行此代码时,显示似乎会像更大的那样闪烁,但是随后它会迅速调整为我不喜欢的默认大小。 I'm guessing this has a simple solution, but I can't seem to find it. 我猜这有一个简单的解决方案,但我似乎找不到。 None of the answers I have found for other questions fix my problem. 我没有找到其他问题的答案来解决我的问题。

I believe the recommendation is not to use pyplot. 我相信建议不要使用pyplot。 With wxPython I also like to use the sized_controls, which hide some of the sizer stuff, but still give you control if you need it and at the same time they comply with the platform UI guidelines. 使用wxPython时,我还喜欢使用size_controls,它们隐藏了一些sizer内容,但是仍然可以根据需要提供控制权,同时它们也符合平台UI准则。

With sizers when you add something you need to tell the container to call Layout/Fit to tell it to adjust itself to the new children. 使用sizer时,添加内容时需要告诉容器调用Layout / Fit,以使其适应新的子代。

You might also want to check out the mpl examples: http://matplotlib.org/examples/user_interfaces/index.html 您可能还想查看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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM