Beispiel: wxPython Liniendiagramm

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dieses Beispiel soll eine Möglichkeit aufzeigen, wie man mit wxPython ein Liniendiagramm erstellen kann.

Bild

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx
import wx.lib.plot as plot


wx.SetDefaultPyEncoding("iso-8859-15")


class MyFrame(wx.Frame):
   
    def __init__(
        self, parent = None, id = -1, title = "Example", size = wx.Size(500, 500)
    ):
        wx.Frame.__init__(self, parent, id, title, size = size)
       
        panel = wx.Panel(self)
       
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)
       
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox_main.Add(vbox, 1, wx.ALL | wx.EXPAND, 5)
       
        canvas = plot.PlotCanvas(panel)
        vbox.Add(canvas, 1, wx.EXPAND | wx.ALL, 5)
       
        coordinates1 = (
            (1, 50), (2, 60), (3, 45), (4, 60), (5, 33), (6, 79),
        )
        coordinates2 = (
            (1, 40), (2, 30), (3, 65), (4, 80), (5, 23), (6, 19),
        )
        lines = (
            plot.PolyLine(
                coordinates1, colour = "green", legend = u" Jänner", width = 1
            ),
            plot.PolyLine(
                coordinates2, colour = "blue", legend = u" Februar", width = 1
            ),
        )
       
        graphics = plot.PlotGraphics(
            objects = lines, title = u"Monatsübersicht", xLabel = u"Monate",
            yLabel = u"Anzahl Verkäufe"
        )
       
        canvas.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
        canvas.SetFontSizeAxis(10)
        canvas.SetFontSizeLegend(7)
        canvas.SetEnableLegend(True)
        canvas.SetXSpec('auto')
        canvas.SetYSpec('auto')
        canvas.SetEnableGrid(True)
       
        canvas.Draw(graphics, xAxis = (0, 12), yAxis = (0, 100))
        #canvas.Draw(graphics)


def main():
    """Testing"""
   
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)

Stichworte: Diagramm Graph Linie Liniendiagramm
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

xxx schrieb:
> würde nur gerne jetzt die
> SetEnablePointLabel Funktion von PlotCanvas aktivieren

Hallo xxx!

---------------
Bitte stelle deine Fragen im Python-Forum und nicht per Email. Wenn du per Email oder PN fragst, dann verpufft die Antwort und niemand außer dir kann davon profitieren.
---------------

Schau dir die Datei "plot.py" an. Du musst mit ``SetPointLabelFunc`` auf eine Funktion zeigen, die direkt in den DC des Canvas zeichnet. Im Beispiel, das in "plot.py" mit drinnen ist, macht das die Funktion ``DrawPointLabel``. Diese kannst du als Beispiel heranziehen.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
rkager
User
Beiträge: 8
Registriert: Sonntag 17. Februar 2008, 19:03

Habe die Datei etwas erweitert, es wird nun der Aktuelle Cursor Wert der einzelnen Linien angezeigt.
Die neuen Zeilen wurden aus plot.py vom wx Paket eingefügt.

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

import wx
import wx.lib.plot as plot


wx.SetDefaultPyEncoding("iso-8859-15")


class MyFrame(wx.Frame):
   
    def __init__(
        self, parent = None, id = -1, title = "Example", size = wx.Size(500, 500)
    ):
        wx.Frame.__init__(self, parent, id, title, size = size)
       
        panel = wx.Panel(self)
       
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)        
       
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox_main.Add(vbox, 1, wx.ALL | wx.EXPAND, 5)
       
        self.client = plot.PlotCanvas(panel)

        ##new declarations
        
        #define the function for drawing pointLabels
        self.client.SetPointLabelFunc(self.DrawPointLabel)
        # Create mouse event for showing cursor coords in status bar
        self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
        # Show closest point when enabled
        self.client.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
        ##end of new declarations

        
        vbox.Add(self.client, 1, wx.EXPAND | wx.ALL, 5)

        
       
        coordinates1 = (
            (1, 50), (2, 60), (3, 45), (4, 60), (5, 33), (6, 79),
        )
        coordinates2 = (
            (1, 40), (2, 30), (3, 65), (4, 80), (5, 23), (6, 19),
        )
        lines = (
            plot.PolyLine(
                coordinates1, colour = "green", legend = u" Jänner", width = 1
            ),
            plot.PolyLine(
                coordinates2, colour = "blue", legend = u" Februar", width = 1
            ),
        )
       
        graphics = plot.PlotGraphics(
            objects = lines, title = u"Monatsübersicht", xLabel = u"Monate",
            yLabel = u"Anzahl Verkäufe"
        )
       
        self.client.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.NORMAL))
        self.client.SetFontSizeAxis(10)
        self.client.SetFontSizeLegend(7)
        self.client.SetEnableLegend(True)
        self.client.SetXSpec('auto')
        self.client.SetYSpec('auto')
        self.client.SetEnableGrid(True)

        ##Activate Labels        
        self.client.SetEnablePointLabel(True)
       
        self.client.Draw(graphics)

        ##show Statusbar for Mouse Position
        self.CreateStatusBar(1)        


    ##Functions from plot.py
    def DrawPointLabel(self, dc, mDataDict):
        """This is the fuction that defines how the pointLabels are plotted
            dc - DC that will be passed
            mDataDict - Dictionary of data that you want to use for the pointLabel

            As an example I have decided I want a box at the curve point
            with some text information about the curve plotted below.
            Any wxDC method can be used.
        """
        # ----------
        dc.SetPen(wx.Pen(wx.BLACK))
        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
        
        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
        px,py = mDataDict["pointXY"]
        cNum = mDataDict["curveNum"]
        pntIn = mDataDict["pIndex"]
        legend = mDataDict["legend"]
        #make a string to display
        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
        dc.DrawText(s, sx , sy+1)
        # -----------

    def OnMouseLeftDown(self,event):
        s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY(event)
        self.SetStatusText(s)
        event.Skip()            #allows plotCanvas OnMouseLeftDown to be called

    def OnMotion(self, event):
        #show closest point (when enbled)
        if self.client.GetEnablePointLabel() == True:
            #make up dict with info for the pointLabel
            #I've decided to mark the closest point on the closest curve
            dlst= self.client.GetClosestPoint( self.client._getXY(event), pointScaled= True)
            if dlst != []:    #returns [] if none
                curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
                #make up dictionary to pass to my user function (see DrawPointLabel) 
                mDataDict= {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\
                            "pointXY":pointXY, "scaledXY":scaledXY}
                #pass dict to update the pointLabel
                self.client.UpdatePointLabel(mDataDict)
        event.Skip()           #go to next handler
        
    def SetPointLabelFunc(self, func):
        """Sets the function with custom code for pointLabel drawing
            ******** more info needed ***************
        """
        self._pointLabelFunc= func
    ##end of new code        
        
def main():
    """Testing"""
   
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
Sorry wegen dem PM, und vielen Dank für die schnelle Hilfe

mfg
Reinhard
Turri
User
Beiträge: 2
Registriert: Donnerstag 17. Juli 2008, 07:48

Hallo Zusammen!

Das obige Beispiel funktioniert sehr gut.

Aber gibt es eine Möglichkeit die Beschriftung für jeden Punkt dauerhaft sichtbar zu machen ohne das OnMotion-Event?

Mein Problem ist, ich habe ein Diagramm mit vielen Werten und an einzelnen Punkten setze ich mir Marker (plot.PolyMarker) und diese Punkte möchte ich beschriften.

Kann mir da jemand weiterhelfen?
Bis jetzt hab ich es über SetPointLabelFunc versucht.
Die Pointlabels werden gezeichnet, allerdings nur ganz kurz angezeigt.
Die sind immer sofort wieder verschwunden.

Gibts eine Möglichkeit Punkte dauerhaft zu beschriften?

Ich dachte das passt ganz gut hier in den Thread.

MfG Turri
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Turri hat geschrieben:Gibts eine Möglichkeit Punkte dauerhaft zu beschriften?
Hallo Turri!

Willkommen im Python-Forum!

Kurze Antwort: Ich glaube nicht. PyPlot ist ziemlich eingeschränkt. Alles was es kann, wird in der wxPython-Demo vorgezeigt. Mehr kann es nicht.

Wenn du mehr brauchst, dann musst du wahrscheinlich auf eine bessere Plot-Engine zurückgreifen.

- http://matplotlib.sourceforge.net/

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Turri
User
Beiträge: 2
Registriert: Donnerstag 17. Juli 2008, 07:48

Hallo Gerold,

Danke für deine Antwort, dann werd ich mir matplotlib mal genauer anschauen. :-)

Danke!

MfG Turri
Antworten