Kapitel 4

Dr. Bernd Kokavecz

Ein Grafik-Tool für den Anfängerunterricht

Angeregt durch die Arbeiten am OSZ Handel (Spolwig, Penon u.a.) wurde eine Klassenbibliothek für die objektorientierte Programmierung im Anfängerunterricht realisiert. Am Oberstufenzentrum existieren entsprechenden Versionen für die Programmierung in Java und in Delphi. An Hand der Klassenbeschreibungen wurde eine weitgehend anwendungskompatible Version in Python geschrieben. Dabei ist festzustellen, dass unter python entsprechende Grafikklassen schon existieren. Um aber möglichst mit gleichen Bezeichnern arbeiten zu können, wurde eine neue Programmierung durchgeführt.

Hier zunächst eine kleine Beschreibung der Klassen: hier klicken!

Hier nun der komplette Quelltext. Wenn Sie einige kleine Testprogramme kennenlernen wollen, die dieses Tool anwenden, so klicken Sie bitte HIER. Dort können Sie auch die zugehörigen Bildschirmphotos betrachten!


Hier noch ein Beispielprogramm aus dem laufenden Unterricht. Es werden zwei unterschiedlich schwere Bälle mit einem (gleichen) Startimpuls in unterschiedlichen Richtungen gestartet. Sie reflektieren an den begrenzenden Wänden der Grundfläche. Die Aufgabe wurde mit unabhängig voneinander laufenden Threads realisiert.

# Die Grafik-Klassen in   graph.py

#! /usr/bin/python

import Tkinter  
from Tkconstants import *
import Canvas                        

class Image:
   """
   /* Bildklasse
   """
   def __init__(self,Name):
      """
      /* Name: string : Dateiname des Bildes
      """
      self.Bild=Tkinter.PhotoImage(file=Name)
      self.Breite=self.Bild.width()
      self.Hoehe=self.Bild.height()

   def get_Bild(self):
      """
      /* liefert das Bildobjekt für 'image' in Canvas.ImageItem
      /* (Darstellung des Bildes auf einer Zeichenfläche)
      """
      return self.Bild

   def get_Breite(self):
      """
      /* liefert die Bildbreite in Pixeln
      """
      return self.Breite
   
   def get_Hoehe(self):
      """
      /* liefert die Bildhoehe in Pixeln
      """
      return self.Hoehe

class TColor:
   """
   /* erste primitive Version mit nur wenigen Farben 
   /* Die Farben können über die deutschen Namen oder über
   /* Zahlen abgerufen werden
   /* Hinweis:   "#fff" entspricht "weiss", 
   /*      statt "#xxx" kann auch "red", "green"  usw. benutzt werden
   /* andere Lösungen mit true-colors sind denkbar
   """
   def __init__(self):
      """
      /* transparent, schwarz, blau, gruen, tuerkis, rot, gelb, grau, weiss
      """
      self.Fnamen = { \
                    0:"transparent", \
                    1:"schwarz" , \
                    2:"blau"    , \
                    3:"gruen"   , \
                    4:"tuerkis" , \
                    5:"rot"     , \
                    6:"gelb"    , \
                    7:"grau"    , \
                    8:"weiss"   \
                 }

      self.Farbe={ \
                    "transparent":"", \
                    "schwarz"    :"#000", \
                    "blau"       :"#00f", \
                    "gruen"      :"#0f0", \
                    "tuerkis"    :"#0ee", \
                    "rot"        :"#f00", \
                    "gelb"       :"#ff0", \
                    "grau"       :"#ccc", \
                    "weiss"      :"#fff" \
                 }

   def getColor(self,nr):
      """
      /* nr : int : 0 .. 8  für die oben angegebenen Farben
      /* liefert die Farbdarstellung für X
      """
      return self.Farbe[self.getFarbnamen(nr)] 

   def getFarbnamen(self,nr):
      """
      /* nr : int : 0 .. 8  für die oben angegebenen Farben
      /* liefert den (deutschen) Bezeichner der Farbnummer (s.o.)
      """
      return self.Fnamen[nr]

   def getFarbe(self,wort):
      """
      /* wort : string :  ein Element aus den oben angegebenen Farben
      /* liefert die Farbdarstellung fuer X
      """
      return self.Farbe[wort]

class TFigur:
   """
   /* interne Hinweise:
   /* ZF ist Referenz auf Zeichenfläche, wird später gesetzt
   /* grafObj ist das aktuelle Grafikobjekt
   """
   def __init__(self):
      """
      /* Alle Grafik-Klassen erben von TFigur. TFigur wird beschrieben durch
      /* folgende Attribute:
      /* X1,Y1 (linke obere Ecke)
      /* X2,Y2 (rechte untere Ecke)
      /* Farbe
      /* Fuellfarbe
      """
      self.X1=20
      self.Y1=20
      self.X2=100
      self.Y2=100
      self.Farben=TColor()
      self.Farbe=self.Farben.getColor(0)
      self.Fuellfarbe=self.Farben.getColor(0)

   def setPos(self,ax1,ay1,ax2,ay2):
      """
      /* ax1,ay1 : int :(linke obere Ecke)
      /* ax2,ay2 : int :(rechte untere Ecke)
      """
      self.X1=ax1
      self.Y1=ay1
      self.X2=ax2
      self.Y2=ay2

   def getXPos(self):
      """
      /* liefert x-Wert der Position der linken oberen Ecke
      """
      return self.X1
 
   def getYPos(self):
      """
      /* liefert y-Wert der Position der linken oberen Ecke
      """
      return self.Y1

   def setFarbe(self,F):
      """
      /* F : string : deutscher Bezeichner (s.o.)
      """
      self.Farbe=self.Farben.getFarbe(F)

   def getFarbe(self):
      """
      /* gibt akt. Farbe zurück : string : Farbrepr. für X
      """
      return self.Farbe

   def setFuellfarbe(self,F):
      """
      /* F : string : deutscher Bezeichner (s.o.)
      """
      self.Fuellfarbe=self.Farben.getFarbe(F)

   def getFuellfarbe(self):
      """
      /* gibt akt. Füllfarbe zurück : string : Farbrepr. für X
      """
      return self.Fuellfarbe

   def pos_versetzen_um(self,dx,dy):
      """
      /* versetzt die Position des heweiligen Grafikobjektes um dx und dy
      """
      self.X1=self.X1+dx
      self.X2=self.X2+dx
      self.Y1=self.Y1+dy
      self.Y2=self.Y2+dy

   def zeigen(self):
      """
      /* zeigt das Grafikobjekt auf dem Schirm an
      """
      pass

   def loeschen(self):
      """
      /* löscht das Grafikobjekt auf dem Schirm 
      """
      self.grafObj.move(1000,1000)

   def entfernen(self):
      """
      /* entfernt das Grafikobjekt aus dem Speicher 
      """
      self.grafObj.delete()


class TLinie(TFigur):
   """
   /* Klasse Linie
   """
   def __init__(self):
      TFigur.__init__(self)
      x = self.getFarbe()
      self.grafObj=Canvas.Line(TFigur.ZF,(self.X1, self.Y1),(self.X2, self.Y2)\
                                                         , {"fill": x})

   def zeigen(self):
      self.grafObj.config(fill=self.getFarbe())
      self.grafObj.coords(((self.X1,self.Y1),(self.X2,self.Y2)))

class TEllipse(TFigur):
   """
   /* Klasse Ellipse
   """
   def __init__(self):
      TFigur.__init__(self)
      x = self.getFarbe()
      y = self.getFuellfarbe()
      self.grafObj=Canvas.Oval(TFigur.ZF, (self.X1, self.Y1), \
                             (self.X2, self.Y2), {"outline": x, "fill": y})

   def zeigen(self):
      self.grafObj.config(fill=self.getFuellfarbe(),outline=self.getFarbe())
      self.grafObj.coords(((self.X1,self.Y1),(self.X2,self.Y2)))

class TKreis(TFigur):
   """
   /* Klasse Kreis
   """
   def __init__(self):
      """
      /* zus. Attribute sind hier: Radus, x-Mittelpunkt, y-Mittelpunkt
      """
      TFigur.__init__(self)
      self.R=0
      self.Mx=0
      self.My=0
      x = self.getFarbe()
      y = self.getFuellfarbe()
      self.grafObj=Canvas.Oval(TFigur.ZF, (self.X1, self.Y1), \
                             (self.X2, self.Y2), {"outline": x, "fill": y})

   def __berechne_Standard(self):
      self.X1=self.Mx-self.R
      self.X2=self.Mx+self.R
      self.Y1=self.My-self.R
      self.Y2=self.My+self.R

   def setRadius(self,r):
      """
      /* r : int : Radius
      """
      self.R=r
      self.__berechne_Standard()

   def getRadius(self):
      """
      /* liefert aktuelle Radiuslänge
      """
      return self.R

   def setMPos(self,ax,ay):
      """
      /* ax, ay : int
      /* setzt Mittelpunktskoordinaten
      """
      self.Mx=ax
      self.My=ay
      self.__berechne_Standard()

   def zeigen(self):
      self.grafObj.config(fill=self.getFuellfarbe(),outline=self.getFarbe())
      self.grafObj.coords(((self.X1,self.Y1),(self.X2,self.Y2)))


class TRechteck(TFigur):
   """
   /* Klasse Rechteck
   """
   def __init__(self):
      TFigur.__init__(self)
      x = self.getFarbe()
      y = self.getFuellfarbe()
      self.grafObj=Canvas.Rectangle(TFigur.ZF, (self.X1, self.Y1), \
                             (self.X2, self.Y2), {"outline": x, "fill": y})

   def zeigen(self):
      self.grafObj.config(fill=self.getFuellfarbe(),outline=self.getFarbe())
      self.grafObj.coords(((self.X1,self.Y1),(self.X2,self.Y2)))


class TText(TFigur):
   """
   /* Klasse Text zur Beschriftung der Zeichenfläche
   """
   def __init__(self):
      """
      /* Attribute sind
      /* Text : string
      /* Schriftart : String  (X-Fonts-Bezeichner)
      /* Zeichen-Hoehe : int : default = 10
      """
      TFigur.__init__(self)
      self.Text=""
      self.Schriftart="*"
      self.Hoehe=10

   def setPos(self,ax,ay):
      """
      /* ax, ay : int : Position des ersten Zeichens
      """
      self.X1=ax
      self.Y1=ay
      
   def setText(self,Text):
      """
      /* Text : string : auszugebender Text
      """
      self.Text=Text

   def setFont(self,Art="*",Grad=10):
      """
      /* Art : string : Font-Name
      /* Grad : int : Zeichengröße
      """
      self.Schriftart=Art
      self.Hoehe=Grad    

   def zeigen(self):
      self.grafObj=Canvas.CanvasText(TFigur.ZF, self.X1, self.Y1, \
             anchor="w", fill=self.Farbe, font=(self.Schriftart, self.Hoehe))
      self.grafObj.insert(0,self.Text)
      

class TZeichenblatt:
   """
   /* Zeichenblatt entspricht Canvas. Mit Init wird ein Bild unterlegt
   /* Zeichenblatt vom Typ TZeichenplatt wird erzeugt und steht zur 
   /* Verfügung.
   """
   def __init__(self):
      pass

   def Init(self,Name):
      """
      /* Init hinterlegt das Bild
      /* Name : string : Dateiname (gif)
      """
      self.oWindow=Tkinter.Tk()  
      self.oWindow.title("Zeichenfläche - nach S. Spolwig    -----   Kokavecz") 
      self.oBild=Image(Name)
      self.X1=0
      self.Y1=0
      self.X2=self.oBild.get_Breite()
      self.Y2=self.oBild.get_Hoehe()
      Geometrie=str(self.X2)+"x"+str(self.Y2)+"+0+0"
      self.oWindow.geometry(Geometrie)
      self.oEbene=Tkinter.Canvas(self.oWindow,relief=SUNKEN, bd=5, \
                                           width=self.X2, height=self.Y2)
      bild=Canvas.ImageItem(self.oEbene,(0,0),anchor="nw", \
                                              image=self.oBild.get_Bild())
      self.oEbene.pack() 
      TFigur.ZF=self.oEbene   
 
  
   def get_Breite(self):
      """
      /* liefert die Bildbreite in Pixeln
      """
      return self.oBild.get_Breite()

   def get_Hoehe(self):
      """
      /* liefert die Bildhoehe in Pixeln
      """
      return self.oBild.get_Hoehe()


   def refresh(self):
      TFigur.ZF.update()

# sollte oZeichenblatt oder mein_Zeichenblatt heißen:
Zeichenblatt = TZeichenblatt()


python zurück zur Startseite

Dr. Bernd Kokavecz
Datum: 25.08.2000
dr.bernd@kokavecz.de