image image


Tutorial: Tkinter und Canvas, Teil 1

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.

Warum Tkinter?

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.

Der erste Canvas

image

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.

Quadrate, Quadrate

image

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.

Die Schmetterlingskurve

image

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.

Es geht noch viel einfacher

image

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) (#)


(Kommentieren)  Tkinter und Canvas, Teil 1 bitte flattrn




Ü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


Werbung


image  image  image
image  image  image