2015-08-30 3 views
1

В приложении wxPython у меня есть встроенный элемент фигуры с фигурой matplotlib. Я хочу иметь возможность переключать фигуру, загружая новую. Однако эта цифра не обновляется.Обновить wxpython рисунок фигуры с новым рисунком

Ответы на подобные темы предполагает, что panel.canvas.draw() и panel.Refresh() должен сделать трюк, но я также пытался panel.Update() и panel.canvas.Refresh(). Я боюсь, что это работает только если вы хотите перерисовать холст с тем же рисунком?

Итак, мой вопрос: как вы заменяете фигуру внутри холста и обновляете ее?

Ниже представлен небольшой (нерабочий) пример. Сначала фигура загружается одной осью. Если вы из встроенной оболочки типа panel.LoadFigure(), новая фигура с 2x2 подзаголовками создается и помещается в холст. Но новая фигура не показана.

import numpy as np 
import wx 
from wx.py.shell import Shell 

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas 
import matplotlib.pyplot as plt 


class ShellPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent) 
     self.shell = Shell(self) 
     self.sizer = wx.BoxSizer(wx.VERTICAL) 
     self.sizer.Add(self.shell, 1, wx.GROW) 
     self.SetSizer(self.sizer) 
     self.Layout() 
     self.Fit() 


class FigurePanel(wx.Panel): 
    def __init__(self, parent): 

     wx.Panel.__init__(self, parent) 
     self.parent = parent 
     self.sizer = wx.BoxSizer(wx.VERTICAL) 
     self.figure, ax = plt.subplots() 
     self.canvas = FigureCanvas(self, -1, self.figure) 
     self.shellpanel = ShellPanel(self) 
     s1 = wx.BoxSizer(wx.VERTICAL) 
     s1.Add(self.canvas, 0, wx.GROW) 
     s1.Add(self.shellpanel, 1 , wx.EXPAND) 
     self.sizer.Add(s1, 5, wx.GROW) 

     self.SetSizer(self.sizer) 
     self.Layout() 
     self.Fit() 

    def LoadFigure(self): 
     self.figure, ax = plt.subplots(2, 2) 
     self.canvas.draw() 
     self.Refresh() 


class FigureFrame(wx.Frame): 
    def __init__(self, parent, id, title, size): 
     wx.Frame.__init__(self, parent, id, title, size=size) 

if __name__ == "__main__": 
    app = wx.App(False) 
    fr = FigureFrame(None, -1, title='Figure Loader', size=(wx.DisplaySize()[0]/2, wx.DisplaySize()[1]*3/4)) 
    panel = FigurePanel(fr) 
    fr.Show() 
    app.MainLoop() 

ответ

1

Есть ли какой-либо причине вы пытаетесь создать новую Figure, а не просто новый Axes на уже определены Figure?

Я хотел бы написать код так:

def LoadFigure(self): 
    self.figure.clf() # clear current figure 
    # add arbitrary number of new Axes 
    self.figure.add_subplot(221) 
    self.figure.add_subplot(222) 
    self.figure.add_subplot(223) 
    self.figure.add_subplot(224) 
    self.canvas.draw() # refresh canvas 

EDIT: Следующий ваш комментарий, я думаю, что проблема в том, что вы создаете новую фигуру, но ваш Canvas все еще ссылается на старый. Я не знаю, можете ли вы изменить это непосредственно в свойствах FigureCanvas, может быть, кто-то, у кого больше опыта, может дать лучший ответ. На данный момент я бы сделал Destroy предыдущий холст и создаю новый объект FigureCanvas с вашей новой фигурой.

def LoadFigure(self): 
    self.figure, ax = plt.subplots(2, 2) 
    self.canvas.Destroy() 
    self.canvas = FigureCanvas(self, -1, self.figure) 
    self.canvas.draw() 
+0

Причина в том, что Im загружает маринованные фигуры из файла. То есть 'fig = pickle.load (filename)'. Это дает новую цифру каждый раз. Поэтому я хочу обновить холст этой новой фигурой. Код примера, который я написал, несколько глупо, как вы показали в своем примере. – pathoren

+0

@pathoren ОК, я понимаю сейчас. Я изменил свой ответ, чтобы предоставить вам что-то, что, я считаю, работает, но это не очень, возможно, есть лучший способ. –

+0

Спасибо @Diziet. У меня было аналогичное решение, как план резервного копирования, но надеялся, что есть более чистый способ сделать это. Я жду, чтобы принять ваш ответ, чтобы узнать, есть ли другие предложения. – pathoren

0

Попробуйте использовать сам рисунок, чтобы сделать свою фигуру, а не pyplot. Обычно это работало для меня, потому что это дает вам больше возможностей для импровизации.

#!/usr/bin/python 

# -*- coding: utf-8 -*- 

import numpy as np 
import wx 
from wx.py.shell import Shell 
from matplotlib.figure import Figure 
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas 
import matplotlib.pyplot as plt 


class ShellPanel(wx.Panel): 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent) 
     self.shell = Shell(self) 
     self.sizer = wx.BoxSizer(wx.VERTICAL) 
     self.sizer.Add(self.shell, 1, wx.GROW) 
     self.SetSizer(self.sizer) 
     self.Layout() 
     self.Fit() 


class FigurePanel(wx.Panel): 
    def __init__(self, parent): 

     wx.Panel.__init__(self, parent) 
     self.parent = parent 
     self.sizer = wx.BoxSizer(wx.VERTICAL) 
     self.figure = Figure(figsize = (8,6.1), dpi =60) 
     self.ax = self.figure.add_subplot(1,1,1) 
     self.enlarged_figure = Figure(figsize = (8,6.1), dpi = 100) 
     self.ax2 = self.enlarged_figure.add_subplot(2,1,2) 
     self.canvas = FigureCanvas(self, -1, self.figure) 
     self.canvas.Show() 
     self.enlarged_canvas = FigureCanvas(self,-1,self.enlarged_figure) 
     self.enlarged_canvas.Show() 

     self.shellpanel = ShellPanel(self) 
     s1 = wx.BoxSizer(wx.VERTICAL) 
     s1.Add(self.canvas, 0, wx.GROW) 
     s1.Add(self.shellpanel, 1 , wx.EXPAND) 
     self.sizer.Add(s1, 5, wx.GROW) 
     self.SetSizer(self.sizer) 
     self.Layout() 
     self.Fit() 

    def LoadFigure(self): 
     self.figure, ax = plt.subplots(2, 2) 
     self.canvas.draw() 
     self.Refresh() 


class FigureFrame(wx.Frame): 
    def __init__(self, parent, id, title, size): 
     wx.Frame.__init__(self, parent, id, title, size=size) 

if __name__ == "__main__": 
    app = wx.App(False) 
    fr = FigureFrame(None, -1, title='Figure Loader', size=(wx.DisplaySize()[0]/2, wx.DisplaySize()[1]*3/4)) 
    panel = FigurePanel(fr) 
    fr.Show() 
    app.MainLoop() 

В типа оболочки в «panel.LoadFigure()» и новая фигура будет отображаться очень быстро, а затем исчезают. Затем введите «panel.canvas.draw()», и новая фигура будет там. Затем введите «panel.LoadFigure()», чтобы загрузить старый рисунок назад. Повторение.

Я не знаю, почему фигура остается скрытой после продолжения MainLoop(), но это своего рода быстрое исправление вашей проблемы.

+0

Изучив это немного, я думаю, что цифры не могут оставаться на дисплее, когда они создаются детьми основного кадра.Например, если вы должны создать новый класс под названием «myFrame», а затем поместите FigurePanel и ShellPanel так, как вы их там, он фактически даже не отобразит панель оболочки, так как она создается внутри класса FigurePanel. Однако, если вы создадите его в главном родительском «myFrame», он останется на дисплее. –

Смежные вопросы