matplotlib und sizer

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Braindie
User
Beiträge: 20
Registriert: Mittwoch 10. Juni 2009, 07:54

Hallo,

ich beschäftige mich gerade mit matplotlib und möchte ein Figure erzeugen Ein Figure im ganzen Frame darzustellen ist keine Problem. Ich möchte jedoch das Figure auf einem Panel darstellen (Für das eigentliche Programm) und das Figure soll sich auch bei veränderbarer Größe des Frames mit verändern.

Entweder hab ich das mit den Sizern noch nicht richtig verstanden oder ich weis auch nicht.
Vielen Dank für eure Anteilnahme

Gruss

Stefan

Erst das Beispiel von Matplotlib:
http://matplotlib.sourceforge.net/examp ... n_wx2.html

und dann meine Idee wie ich es verändern wollte:
Das Figure ändert aber leider seine Größe nicht wenn man das Frame maximiert.

Code: Alles auswählen

#!/usr/bin/env python

from numpy import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import wx

class CanvasFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self,None,-1,
                         'CanvasFrame',size=(550,350))
        panel=wx.Panel(self)
        
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0,3.0,0.01)
        s = sin(2*pi*t)

        self.axes.plot(t,s)
        self.canvas = FigureCanvas(panel, -1, self.figure)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(panel, 1, wx.EXPAND)

    def OnPaint(self, event):
        self.canvas.draw()

class App(wx.App):

    def OnInit(self):
        frame = CanvasFrame()
        frame.Show(True)

        return True

app = App(0)
app.MainLoop()
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

versuche mal:

Code: Alles auswählen

...
        self.figure = Figure(figsize=(7, 6), dpi=100)
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0,3.0,0.01)
        s = sin(2*pi*t)

        self.axes.plot(t,s)
        self.canvas = FigureCanvas(self, -1, self.figure)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.ALL|wx.TOP|wx.GROW,2)
        self.SetSizer(self.sizer)
        self.Fit()
...
und etwas aufräumen ;-)

HTH,
Christian

PS Dazu gibt es auch noch eine Toolbar, die ganz nützlich ist. Willst Du erstmal selber versuchen? ;-)
Braindie
User
Beiträge: 20
Registriert: Mittwoch 10. Juni 2009, 07:54

Hi,

leider funktioniert das nicht. Man sieht das Panel im Frame und einen kleinen grauen Kasten in der oberen linken Ecke.
Irgendwie macht folgende Zeile Probleme:

Code: Alles auswählen

self.SetSizer(self.sizer)
Ich denke mal das Problem liegt an der Einstellung, dass man die Größe des Figure definieren kann und dann kommt noch die Angabe des dpi-Wertes dazu. Wenn man nun das Frame maximiert müssten sich diese Angaben auch ändern aber ich habe keine Ahnung wie.

Zur Toolbar:
Ich habe diese mit Absicht aus dem Quelltext des Beispieles rausgeschmiessen um weniger Code zu posten, aber danke für den Hinweis.

Zum Aufräumen:
mmhh...ich werde mir mühe geben :)

Gruss Stefan
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi Stefan,
Braindie hat geschrieben:leider funktioniert das nicht. Man sieht das Panel im Frame und einen kleinen grauen Kasten in der oberen linken Ecke.
Wieso Panel? In meinem Code ist kein Panel.

Was die dpi-Angabe anbelangt: Die kann man auch weglassen und sich auf den default-Wert verlassen (von dem ich gerade nicht weiß wie er lautet). Aber Deine Bildschirmauflösung ist wahrscheinlich nicht höher und mpl-plots haben per default - glaube ich eine höhere Auflösung. Also setzte ich die Auflösung zum Speichern von Plots wieder rauf, zur Bildschirmanzeige runter. Ehrllich gesagt: Das war mal sinnvoll: Ich weiß nicht, ob das immer noch viel bringt.

Was die Größeneinstellung anbelangt: Die kannst Du natürlich anpassen, aber bei mir funktioniert das vom Prinzip und ich frage mich, wo sonst das Problem liegen könnte. Was ist Deine wx-Version?

Zur Toolbar: Ok, werde ich nicht wieder auf den Tisch bringen ;-).

Gruß,
Christian
Braindie
User
Beiträge: 20
Registriert: Mittwoch 10. Juni 2009, 07:54

Hi Christian,

In deinem Codeschnippsel hast du das Canvasfigure direkt auf das Frame bezogen.
self.canvas = FigureCanvas(self, -1, self.figure)
Das funktioniert super.
Ich wollte das Canvasfigure aber auf ein Panel legen, da ich später noch andere Objekte in das Frame legen will.
self.canvas = FigureCanvas(panel, -1, self.figure)
Ich habe mein Problem aber gelöst. Anbei der Code wie ich das Figure eigentlich darstellen möchte und komischerweise funktioniert es wunderbar.
Ich glaube manchmal muss man einfach mal ein bisschen darüber reden/schreiben und dann werden einem dinge selber klarer.

Danke für die Info mit dem dpi Wert, da ich die Figures später eh noch abspeichern werde.

Gruss Stefan

p.s. Ich schau mir jetzt mal die Toolbar an und werde sie einbauen :wink:
p.p.s. Wenn jemand die Muße kann er mir mal bitte die Zeilen mit den Boxsizern und dem SetSizern erklären. Ich hab zwar schon einiges darüber gelesen aber irgendwie ist mir as noch nicht richtig klar. Mercy

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: iso-8859-15 -*- 
import wx
import numpy
import matplotlib 
matplotlib.use('WXAgg') 
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas 
from matplotlib.figure import Figure

t = numpy.arange(0.0,3.0,0.01) 
s = numpy.sin(2*numpy.pi*t) 

class MyFrame(wx.Frame):
    def __init__(
        self, parent = None, title = "Test", size = wx.Size(550, 420)):
        '''main frame'''
        wx.Frame.__init__(self, parent, -1, title, size = size)
        main_panel=wx.Panel(self)

        vbox_main = wx.BoxSizer(wx.VERTICAL)
        main_panel.SetSizer(vbox_main)

        hbox = wx.BoxSizer(wx.HORIZONTAL)
        vbox_main.Add(hbox, 1, wx.EXPAND | wx.ALL, 3)
        
        left_box = wx.TextCtrl(main_panel, size = (200, -1))
        hbox.Add(left_box, 0, wx.EXPAND | wx.ALL, 3)
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox.Add(vbox, 1, wx.EXPAND)
        
        top_box = wx.TextCtrl(main_panel, size = (-1, 250), style = wx.TE_MULTILINE)
        vbox.Add(top_box, 0, wx.EXPAND | wx.ALL, 3)       
        
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111) 
        self.axes.plot(t,s) 
        self.canvas = FigureCanvas(main_panel, -1, self.figure) 
        vbox.Add(self.canvas, 1, wx.EXPAND | wx.ALL,3) 

if __name__ == "__main__":
    app=wx.PySimpleApp()
    frame = MyFrame()
    frame.Show()
    app.MainLoop()
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Na ja, jetzt setzt Du das Panel aber auch in einen Sizer unabhängig vom figure-Objekt ;-). Sorry, da habe ich Dich falsch verstanden - obwohl Deine Intention ja eigentlich nicht falsch zu verstehen war.

Bzgl. Boxsizer: Das sind einfache Sizer. Davon gibt es - wie Du sicher weißt versch. Varianten. Die Demo ist bietet einen sehr guten Überblick in den man sich leicht einfühlen kann - ich hoffe das ist nicht Eulen nach Athen tragen ;-).

widget.SetSizer sagt dem widget welchem sizer es "gehorchen" soll. Im Gegensatz zu sizer.Add(widget), was dem sizer ein widget zuweißt: Damit wird gewissermaßen dem Sizer der Auftrag gegeben das widget entsprechend einzuordnen. Ich nutze meißt nur sizer.Add(), weil das einen - für mich - übersichtlichen Aufbau erlaubt und widget.SetSizer() allenfalls am Ende. Ist ein bißchen Geschmackssache, aber wenn ich mich nicht irre ist mein Weg der orthodoxe ;-).

Gruß,
Christian
Braindie
User
Beiträge: 20
Registriert: Mittwoch 10. Juni 2009, 07:54

Servus Christian,

vielen Dank nochmal für deine Hilfe.

Gruss

Stefan

p.s. Bis zur nächsten Herausforderung :wink:
Antworten