Der Erfolg von Processing zeigt, daß der Nutzer in vielen Fällen mit dem Einfachsten zufrieden ist. Eine ausgefeilte IDE und eine Graphikausgabe mit vielen GUI-Elementen wird oft gar nicht benötigt, ein einfaches Graphikfenster, in das der Nutzer über eine Programmier- oder Skriptsprache hineinzeichnen kann, reicht ihm völlig aus. Und so kam mir die Idee, dies auch einmal mit Tkinter und Python auszuprobieren.
Tkinter ist seit den Anfängen von Python dabei und schon lange in der Standardbibliothek enthalten. Der Nutzer muß also nicht erst umständlich irgendetwas von irgendwoher installieren, sondern er kann es einfach aufrufen. Das Versprechen batteries included ist hier also eingelöst.
Zwar gibt es oder gab es auf den ersten Blick durchaus attraktivere Alternativen, wie z.B. PyGlet und die darauf aufbauende Nodebox for OpenGL, aber die Weiterentwicklung dort stockt. Eine andere Alternative ist sicher auch PyGame, das ich in einigen Fällen auch nutze, aber zumindest unter MacOS X existiert hier noch keine 64-Bit-Version und so ist die Software unter einem 64-Bit Python 2.7 nicht zu nutzen. Aber natürlich gibt es Aufgaben, die unter Tkinter nicht zu lösen sind und für die ich gerne auf PyGame unter Python 2.6 zurückgreife.
Zugegeben, Tkinter hatte früher auf dem Mac ein etwas anrüchiges Aussehen, zusehr muteten die Fenster und GUI-Elemente nach Motif an, aber seit Jahren schon ist ein Tkinter-Fenster von einem nativen Fenster des Gast-System kaum mehr zu unterscheiden. Und mit Tkinter bekommt man wirklich einfach ein Fenster geöffnet, in das hineingezeichnet werden kann.
Eine einfache digitale Leinwand auf den Monitor zu zaubern, in der der Nutzer via Python etwas hineinzeichnen kann, ist ziemlich einfach:
from Tkinter import *
root = Tk()
root.title("Tk Canvas")
cw = 400 # canvas width
ch = 400 # canvas height
canvas = Canvas(root, width = cw, height = ch, background = "white")
canvas.grid(row = 0, column = 0)
root.mainloop()
Wie Ihr seht, ist das Progrämmchen wirklich straightforward. Erst wird alles von Tkinter importiert und dann ein Root-Fenster festgelegt und mit einer Titelzeile versehen. Danach legt Ihr die Höhe und Breite der Leinwand fest, auf der Ihr zeichnen wollt und dann erstellt Ihr den Canvas/die Leinwand in der gewünschten Höhe mit einem weißen Hintergrund.
Schließlich legt Ihr noch fest, wo im Root-Fenster der Canvas
erscheinen soll. Tkinter kennt einige ziemlich ausgefeilte Packer,
die versuchen, den Platz, den die Widgets im Root-Fenster
einnehmen, möglichst optimal zu verteilen, ich habe mich aber hier
für die einfachste Möglichkeit entschieden, den »Gitter«-Packer
grid
, der in diesem Falle nur aus einem Gitterelement besteht, daß
das Hauptfenster voll ausfüllen soll. (Wie alles in Python – und in
der Informatik überhaupt – werden die Reihen und Spalten des Gitters
von Null an gezählt.)
Zu guter Letzt schickt Ihr das Hauptfenster in die mainloop()
, in
der es auf Ereignisse, die der Nutzer auslöst, wartet. Zur Zeit kann
er allerdings nur die Fenstergröße verändern oder das Hauptfenster
schließen und damit das Programm beenden.
Als nächstes möchtet Ihr sicher in das schöne neue Graphikfenster
etwas hineinzeichnen. Beginnen wir zum Anfang mit etwas Einfachem,
z.B. mit einer Reihe von ineinander verschachtelten Quadraten. Dafür
schreibt Ihr an die Stelle, bevor die mainloop()
aufgerufen wird, also
zwischen canvas.grid(row = 0, column = 0)
und root.mainloop()
:
x_center = cw/2
y_center = ch/2
x_width = y_height = 300
farbe = "darkblue"
canvas.create_rectangle(x_center-x_width/2, y_center-y_height/2,
x_center+x_width/2, y_center+y_height/2,
fill = farbe)
x_width = y_height = 200
farbe = "darkred"
canvas.create_rectangle(x_center-x_width/2, y_center-y_height/2,
x_center+x_width/2, y_center+y_height/2,
fill = farbe)
x_width = y_height = 100
farbe = "darkgreen"
canvas.create_rectangle(x_center-x_width/2, y_center-y_height/2,
x_center+x_width/2, y_center+y_height/2,
fill = farbe)
Auch wenn es hier noch nicht so recht deutlich wird, Tkinters Canvas
zählt die Koordinaten – wie bei fast allen anderen
Graphikbibliotheken auch – von links oben nach rechts unten, (0, 0)
ist also die linke obere Ecke des Fensters und (399, 399)
die rechte untere Ecke.
Als Nächstes will ich Euch einmal etwas Anspruchvolles zeichnen lassen. Die Schmetterlingskurve benutze ich schon seit Urzeiten für meine ersten Graphik-Experimente mit neuen Werkzeugen. Die Berechnung benötigte seinerzeit auf einem mit unglaublichen 8 MHZ ausgestatteten Atari-ST mehrere Minuten, heutzutage geht es natürlich viel schneller – dafür sieht man aber leider nicht mehr, wie sich der Schmetterling selber zeichnet.
Auch hier ist das Programm wieder straightforward:
from Tkinter import *
# für die Sinus- und Cosinus-Funktionen
import math
root = Tk()
root.title("Schmetterlingskurve")
cw = 400 # canvas width
ch = 400 # canvas height
canvas = canvas_1 = Canvas(root, width = cw, height = ch, background = "white")
canvas_1.grid(row = 0, column = 0)
theta = 0.0
while theta < 75.39:
r = math.exp(math.cos(theta)) - 2*math.cos(4*theta) + (math.sin(theta/12))**5
# aus Polarkoordinaten konvertieren:
x = r*math.cos(theta)
y = r*math.sin(theta)
# auf Canvas-Größe skalieren
xx = (x*cw/10) + cw/2
yy = (y*ch/10) + ch/2
if (theta == 0.0):
canvas.create_line(xx, yy, xx, yy)
else:
canvas.create_line(xOld, yOld, xx, yy)
xOld = xx
yOld = yy
theta = theta + 0.02
root.mainloop()
Für die Sinus- und Cosinus-Berechnung mußte zusätzlich noch das Module math
importiert werden. Bei der eigentlichen Kurve wird θ in kleinen Schritten hochgerechnet und dann ρ in Abhängigkeit von θ berechnet (im Programm als theta
und r
bezeichnet).
Mit den folgenden Zeilen
x = r*math.cos(theta)
y = r*math.sin(theta)
erfolgt die Umrechnung von karthesischen Koordinaten in Polarkoordinaten. Und dann werden die kleinen Linienstücke nach und nach gezeichnet und θ hochgezählt.
Ich muß Euch noch ein Geständnis machen: Es geht natürlich noch viel einfacher – hat aber dann nichts mehr mit Tkinter zu tun. Mathematische Kurven würde ich auch heute nicht mehr damit zeichnen wollen. Mit NumPy und der Matplotlib geht es viel schneller und dazu auch noch ohne eine einzige Schleife programmieren zu müssen. Schaut selbst:
import matplotlib.pyplot as plt
import numpy as np
theta = np.arange (.0, 75.39, .02)
r = np.exp(np.cos(theta)) - 2*np.cos(4*theta) + (np.sin(theta/12))**5
x = r*np.sin(theta)
y = r*np.cos(theta)
plt.plot(x, y)
plt.show()
Wenn etwas straightforward ist, dann ist es dies. Die Stärke der NumPy-Arrays und die einfache Bedienung der Matplotlib machen die Ausgabe beinahe zu einem Kinderspiel. Daher ist Tkinter vielleicht nicht mehr das geeignete Werkzeug, um mathematische Figuren zu zeichnen, aber zum einen wollte ich Euch einfach einmal zeigen, wie es geht und zum anderen gibt es ja noch vieles andere, was Ihr – vielleicht sogar verbunden mit einfachen Animationen – auf den Monitor Eures Computers zaubern wollen.
2 (Email-) Kommentare
Netter Anfang!
Wenn Du jetzt noch ganz kurz erklären könntest, wie man MatPlotLib oder vielleicht auch das neue Spielzeug avoplot (https://code.google.com/p/avoplot/) mit Tkinters Canvas verheiratet, dann hätte man mit deinem Tutorial schon fast alle nötigen Grundlagen um eine stand-alone Visualisierung von Daten zu basteln…
– Ingo K. (Kommentieren) (#)
Gemach! Gemach! Das nette Büchlein Matplotlib for Python Developers zeigt unter anderem, wie man die Matplotlib mit den diversen GUI-Toolkits verbindet (leider – soweit ich mich erinnere, nur für GTK+, Qt4 und wxWidgets, aber nicht für Tkinter). Das sollte aber ähnlich funktionieren. Ich werde probieren und bei Erfolg später darauf zurückkommen.
– Jörg Kantel (Kommentieren) (#)
Über …
Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter, Autor, Netzaktivist und Hundesportler — Reihenfolge rein zufällig). Hier steht, was mir gefällt. Wem es nicht gefällt, der braucht ja nicht mitzulesen. Wer aber mitliest, ist herzlich willkommen und eingeladen, mitzudiskutieren!
Alle eigenen Inhalte des Schockwellenreiters stehen unter einer Creative-Commons-Lizenz, jedoch können fremde Inhalte (speziell Videos, Photos und sonstige Bilder) unter einer anderen Lizenz stehen.
Der Besuch dieser Webseite wird aktuell von der Piwik Webanalyse erfaßt. Hier können Sie der Erfassung wiedersprechen.
Werbung