zusammengesetzter Pfeil...

Plattformunabhängige GUIs mit wxWidgets.
Benutzeravatar
Batt0sa1
User
Beiträge: 15
Registriert: Montag 21. April 2008, 23:15

zusammengesetzter Pfeil...

Beitragvon Batt0sa1 » Montag 21. April 2008, 23:40

Hi, mein erster Beitrag und erstmal Hallo an alle / Hello World,

ich versuche gerade einen Pfeil aus meheren einzelnen (wx.Pen) Strichen zu erzeugen.
Die einzelnen Striche sollen später von einem Übergabewert abhängig sein (momentan noch hart gecoded).
Falls es jemanden was sagt, es geht in die Richtung Sankey-Diagramm.

Die einzelnen Pfeile habe ich schon zusammengesetzt gekriegt, nun stellt sich die Frage, wie erstelle ich daraus einen Pfeil?
momentan sieht es so aus:

Bild

und mein Ziel wäre das hier (oder so ähnlich):

Bild

Mein Code:
(ich bin neu bei Python und relativ unerfahren, ich bitte um Nachsicht ;))
Die Kommentare waren i.d.R. Notizen für mich...
:)


Code: Alles auswählen

#!/usr/bin/pythonw
import wx

class DrawPanel(wx.Panel):

   def __init__(self, parent):
       wx.Panel.__init__(self, parent, -1)
       wx.EVT_PAINT(self, self.Strich)
   
   def OnPaint(self, list, St_x, St_y, En_x, En_y):
       dc = wx.PaintDC(self)
       #dc.Clear()
       dc.SetPen(wx.Pen(list[0], list[1])) #Farbe, Breite
       dc.DrawLine(St_x, St_y, En_x, En_y) # x1,y1 ,x2, y2
      
   def Strich(self, event="none"):
      #Die Variablen mit Uebergabewerten loesen ;)
      Objects = [("nothing", 25, 'grey'), ("Apfel", 18, 'green'), ("Birne", 12, 'Blue'), ("Banane", 8, 'yellow')]
      St_x= 0
      St_y= 20
      En_x=200
      En_y= 20
      
        for _ in Objects:

         #Die Luecke zwischen den Strichen kommt daher, weil wx.pen um die Koords "herum" zeichnet --> die y Werte stimmen nicht mehr --> Luecke
         list=[]
         list.insert(len(list),_[2])# Farbe Bsp.: list('RED', 5)
         list.insert(len(list),_[1])# Menge
         # um das drumherumzeichnen auszugleichen, nochmal die Haelfte dazu addieren
         St_y1 = St_y + list[1]/2
         En_y1 = En_y + list[1]/2
        
         self.OnPaint(list, St_x, St_y1, En_x, En_y1)
         St_y = St_y + list[1]
         En_y = En_y + list[1]
         print 'St_y: (in Haupt Fkt.)', St_y, 'fuer ', list
         #print 'Strich: ok'


if __name__ == "__main__":
  app = wx.PySimpleApp(0)
  frame = wx.Frame(None, -1, "TestSankey",
     size=(200, 100))
  DrawPanel(frame)
  frame.Show(True)
  app.MainLoop()



Ich wäre über jegliche Hilfe dankbar :D

Bisher hatte ich gedacht, entweder die Endwerte abzufangen und 2 Dreiecke mit Hintergrundfarben oder Alphawerten zu zeichnen, oder irgendwas zu nutzen, was mir aus dem einen Pfeil macht (Shape o.ä.?)

Würde mich absolut freuen wenn ihr mir weiterhelfen könntet :)
Benutzeravatar
Batt0sa1
User
Beiträge: 15
Registriert: Montag 21. April 2008, 23:15

Beitragvon Batt0sa1 » Mittwoch 23. April 2008, 00:28

Nungut...
Ein wenig weiter bin ich jetzt ja :)
So sieht es gerade aus:

Bild

Der Code:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
    Modul:          Sankey
    Description:    creates (depending on return values 'Menge', start(St_x, St_y) and goal(En_x, En_y)) a sankey
    Version:        0.2a
    Copyright:      2008 by Robert Schröder
    License:        GPL
    Requirements:   Python 2.5
"""
import wx
import wx.lib.ogl as ogl

class DrawPanel(wx.Panel):
   def Clipping(self, Pf_y1, En_x, Pf_y2, laenge):
      Proz = En_x -laenge * 11 / 100
      Proz=int(Proz)
      dc = wx.PaintDC(self)
      #dc.SetBrush(wx.Brush('Red'))
      #dc.DrawRectangle(St_x, St_y, En_x, En_y)
      #pen=wx.Pen('black', 1) #Farbe, Breite
      #pen.SetCap(wx.CAP_BUTT) # fuer's Enden "abschneiden"
      #dc.SetPen(pen)
      Mitte = ((Pf_y2-Pf_y1)/2 + Pf_y1)
      
      #Pfeil-Shape       
      points = (((En_x, Mitte), (En_x, Pf_y1), (Proz, Pf_y1),(En_x, Mitte), (En_x, Pf_y2), (Proz, Pf_y2)))
      Pfeil= wx.RegionFromPoints(points)
      dc.SetClippingRegionAsRegion(Pfeil)
      
      #Notlösung, wenn clipping nicht klappt: drüberzeichnen :)
      dc.SetBrush(wx.Brush('white'))
      rect = Pfeil.GetBox()
      dc.DrawRectangleRect(rect)
      dc.DestroyClippingRegion()
      #1.Dreieck
      #dc.DrawLine(En_x, Mitte, En_x, Pf_y1)
      #dc.DrawLine(En_x, Pf_y1, Proz_5, Pf_y1)
      #dc.DrawLine(En_x, Mitte, Proz_5, Pf_y1 )
      #2. Dreieck
      
      #dc.DrawLine(En_x, Mitte, En_x, Pf_y2)
      #dc.DrawLine(En_x, Pf_y2, Proz_5, Pf_y2)
      #dc.DrawLine(En_x, Mitte, Proz_5, Pf_y2 )
      
      #Pfeil2=[(En_x, Mitte) ,(En_x, Pf_y2) , (Proz_5, Pf_y2)]
      #clipping_unten = wx.RegionFromPoints(Pfeil2)
      #tria = clipping_unten.GetBox()
      #dc.SetClippingRegionAsRegion(clipping_unten)
      
      #dc.DestroyClippingRegion()
      #dc.DrawRectangle(90, 30, 50, 50)
      #region1 = wx.Region(80, 20, 50, 50)
      #region2 = wx.Region(90, 30, 50, 50)
      #region2.SubtractRegion(region1)
      #rect = region2.GetBox()
      #dc.SetClippingRegionAsRegion(region1)
      #dc.SetBrush(wx.Brush('Red'))
      #dc.DrawRectangleRect(rect)
      #dc.DestroyClippingRegion()

   def __init__(self, parent):
       wx.Panel.__init__(self, parent, -1)
       wx.EVT_PAINT(self, self.Strich)
   
   def OnPaint(self, Objects, zaehler, St_x, St_y, En_x, En_y):
       dc = wx.PaintDC(self)
       #dc.Clear()
       pen=wx.Pen(Objects[zaehler][2], Objects[zaehler][1]) #Farbe, Breite
       pen.SetCap(wx.CAP_BUTT) # fuer's Enden "abschneiden"

       dc.SetPen(pen)
       dc.DrawLine(St_x, St_y, En_x, En_y) # x1,y1 ,x2, y2
      
   def Strich(self, event="none"):
      #Die Variablen mit Uebergabewerten loesen ;)
      Objects = [("Luft", 25, 'grey'), ("Apfel", 18, 'green'),
               ("Birne", 12, 'Blue'), ("Banane", 8, 'yellow')]
      St_x= 0
      St_y= 20
      En_x=200
      En_y= 20
      Pf_y1 = St_y
      zaehler = 0      
        for _ in Objects:

         #Die Liste wird erstellt, damit SetPen(s.o.) die Werte 'einfach' kriegt
         #Die Luecke zwischen den Strichen kommt daher, weil wx.pen um die Koords "herum" zeichnet --> die y Werte stimmen nicht mehr --> Luecke


         # um das drumherumzeichnen auszugleichen, nochmal die Haelfte dazu addieren
         St_y1 = St_y + _[1]/2
         En_y1 = En_y + _[1]/2

         self.OnPaint(Objects, zaehler, St_x, St_y1, En_x, En_y1)
                 
         St_y = St_y + _[1]
         En_y = En_y + _[1]
         Pf_y2= En_y
         print 'St_y: (in Haupt Fkt.)', St_y, 'fuer ', Objects[zaehler][0], ' bei der Menge', Objects[zaehler][1]
         #print 'Strich: ok'
         zaehler = zaehler + 1
        #Pfeil (auf die Spitzen 2 Dreicecke zeichnen)
        laenge = (En_x-St_x)
        self.Clipping(Pf_y1, En_x, Pf_y2, laenge)
     


if __name__ == "__main__":
  app = wx.PySimpleApp(0)
  frame = wx.Frame(None, -1, "TestSankey",
     size=(200, 100))
  DrawPanel(frame)
  frame.Show(True)
  app.MainLoop()


Ein wenig verbessert (List und so ;))
Jedenfalls, würde ich gern Clipping einsetzen, nur irgendwie funktioniert das nicht...
Die Fkt. wx.PolygonShape hat bei mir nicht wirklich funktioniert :(
Kann es daran liegen, dass es in einer anderen Fkt. aufgerufen wird?
Also z.B. eine Schicht über den Strichen liegt und sie deshalb nicht partiell löscht?

Die Lösung die ich mir jetzt erdacht habe, ist ja auch mehr halbgar...
Wenn ich den Code richtig verstehe zeichne ich mir noch ein Viereck, welches nicht vollständig dargestellt wird (daher auch die schwarzen Randstriche)


Hat da jemand ne Idee?
Also eine Verbesserungsmöglichkeit, die er mir preisgeben möchte :D
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

Beitragvon sechsrad » Freitag 25. April 2008, 18:09

versuch mal "pygame" mit "wx" zu mischen. ist eine gute sache für die grafische darstellung.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder