verdammt, ich kapier es einfach nicht

Fragen zu Tkinter.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Donnerstag 10. Juli 2008, 18:31

EyDu hat geschrieben:Ein Sechseck per Hand zu erzeugen ist auch nicht besonders elegant.
Der Unterschied zwischen deinem Code und dem oben (an der Stelle) besteht doch aus mathematischer Sicht im wesentlichen darin, dass du mit trigonometrischen Funktionen arbeitest und man oben ohne auskommt (und, ja, natürlich ist ein Einzeiler eleganter ...). "Per Hand" ist das nun ja nicht mehr (am Anfang dieses Threads sieht der Code noch anders aus ...), sondern eben mit Pythagoras berechnet.

M.E. besser mit Pythagoras und mathematisch weniger ausgefeilt und dafür selbst entwickelt und verstanden, als ein Stück fertigen Codes abzutippen ohne zu verstehen, was dahinter steckt. Noch besser ist natürlich, wenn man die trigonometrische Variante auch versteht. Ab Klasse 10 sollte das möglich sein ... :wink:
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Donnerstag 10. Juli 2008, 19:25

hoppala, da habe ich aber einiges aufzuarbeiten. Eben genau weil ich es verstehen möchte. VIELEN VIELEN DANK ->

so ein Beispiel habe ich einmal gebraucht.

Ich werde mich jetzt mal in Ruhe da durch wühlen und mit Sicherheit noch viele Fragen dazu stellen.

Danach kommen dann die ganzen Ergänzungen dran.

Gab es nicht einen "Editor", der alles Zeilenweise "abarbeiten konnte ?

Ich denke, das würde mir nochmals weiterhelfen

TOLLES Forum hier, da werden sie geholfen.

Kai
imac
20 Zoll
2,4 ghz
Benutzeravatar
wuf
User
Beiträge: 1419
Registriert: Sonntag 8. Juni 2003, 09:50

Donnerstag 10. Juli 2008, 20:57

Hallo derkai

Es geht gleich weiter. Hier habe ich einer der Vorschläge von 'numerix' in das bestehende Code-Snippet integriert.

Hier ist die erste Variante der Code-Reduzierung:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Skriptname derkai_05_02_01 (10.07.2008)

import Tkinter as tk
from math import sqrt,sin,cos,pi
from random import choice

def calculate_polygon_points(laenge,xorg,yorg):
    """Berechne die Eckpunkte für ein Sechseck"""

    x1 = xorg
    y1 = yorg
    x2 = x1 + laenge
    y2 = y1
    x3 = x2 + (laenge/2.0)
    y3 = y2 + ((laenge * sqrt(3)/2))
    x4 = x2
    y4 = (sqrt(3) * laenge) + y2
    x5 = x1
    y5 = y4
    x6 = x1 - (laenge / 2.0)
    y6 = y3

    #~~ Gebe die berechneten Eckpunkte in einer Liste zurück
    return [x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6]

def create_hex_polygon(spiel_feld,xpos,ypos,points,farbe):
    """Erzeugt das grafische Sechseck-Objekt"""

    #~~ Variante 'numerix'
    return spiel_feld.create_polygon([value+n%2*ypos+(n+1)%2*xpos for n,
                value in enumerate(points)],outline="black",fill=choice(farbe))

def calculate_xyoffset(points):
    """Berechnet die X- und Y-Versatzabstände"""

    x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6 = points

    laenge = x2 - x1
    xoffset = laenge + (x3-x2)
    yoffset = y5 - y1

    return (xoffset,yoffset)

def main():
    #~~ Erzeugt das Hauptfenster
    # master = Tk() -> (ersetzen durch folgende Zeile)
    master = tk.Tk()
    # spiel = Canvas(master, width=1024, height=768) (ersetzen durch folgende Zeile)
    spiel = tk.Canvas(master, width=1024, height=768)
    spiel.pack()

    hex_laenge = 20 # Bestimmt die Sechseckgrösse
    hex_xorg = 25
    hex_yorg = 15

    #~~ Eckpunkte für das Sechseck berechnen
    hex_point_list = calculate_polygon_points(hex_laenge,hex_xorg,hex_yorg)

    #~~ Horizontaler- & Vertikaler-Versatz die Sechseck-Platzierung berechnen
    xoffset, yoffset = calculate_xyoffset(hex_point_list)

    xpos = xorg = 10           # X Start-Koordinate
    ypos = yorg = 10           # Y Start-Koordinate
    columns = 30               # Anzahl vertikale Reihen
    rows = 10                  # Anzahl horizontale Reihen
    farbe = ("yellow","green") # Zufalls-Farben

    toggle = 0

    #~~ Platziere den zweidimensionalen Sechseck-Array
    for x in xrange(columns):
        for y in xrange(rows):
            create_hex_polygon(spiel,xpos,ypos,hex_point_list,farbe)
            ypos += yoffset

        xpos += xoffset

        if not toggle:
            toggle = 1
            ypos = yorg + yoffset/2.0
        else:
            toggle = 0
            ypos = yorg

    master.mainloop()

main()
Mich bringen Einzeiler als Nicht-Apotheker immer noch zum stottern. Aber sie tragen schon viel zur Skript-Komprimierung bei.

Danke 'numerix' für deinen Vorschlag!

Als nächste zweite Variante versuche ich den Vorschlag von 'EyDu' zu integrieren, welcher wie ich jetzt schon vermute noch eine beachtlichere Code-Reduktion ergeben. wird. EyDu eventuell habe ich als Nicht-Mathematiker in einem nächsten Post noch ein(ige) Frage(n) an dich.

Auch dir vielen Dank für den Vorschlag!

Gruss wuf :wink:
Take it easy Mates!
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Donnerstag 10. Juli 2008, 21:10

nicht soooo viel, ich muß doch auch irgendwann einmal schlafen. Kleiner Scherz -

Code: Alles auswählen

    #~~ Platziere den zweidimensionalen Sechseck-Array
    for x in xrange(columns):
        for y in xrange(rows):
            create_hex_polygon(spiel,xpos,ypos,hex_point_list,farbe)
            ypos += yoffset

        xpos += xoffset
hier habe ich ein problem mit,

in Zeile 5 wird die Funktion create_hex_polygon aufgerufen. OK !
Dieser werden dann folgende Werte übergeben: "spiel", usw.

"spiel" ist mir nicht klar.
vor allem deswegen, weil in der Funktion als solches : spiel_feld, usw... steht.

An sonsten ist die Anzahl der übergeben Argumente vorerst verständlich.
Aber was wird bei "spiel" -> "spielfeld" übergeben ???

Eine Funktion wird doch nach folgendem Schema aufgeruen

Name (Argumente)
return

oder ???

Kai
Zuletzt geändert von derkai am Donnerstag 10. Juli 2008, 21:20, insgesamt 1-mal geändert.
imac
20 Zoll
2,4 ghz
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 10. Juli 2008, 21:15

Das Problem ist, dass "ypos" beim Verlassen der inneren Schleife nicht wieder auf den ursprünglichen Wert zurückgesetzt wird. Also entwender:

Code: Alles auswählen

    ycopy = ypos
    for x in xrange(columns):
        ypos = ycopy
        for y in xrange(rows):
            create_hex_polygon(spiel,xpos,ypos,hex_point_list,farbe)
            ypos += yoffset

        xpos += xoffset
oder

Code: Alles auswählen

    for x in xrange(columns):
        for y in xrange(rows):
            create_hex_polygon(spiel,xpos+x*xoffset,ypos+y*yoffset,hex_point_list,farbe)
Edit: Ach, da fehlt der untere Teil der beiden Schleifen, dann ist mein Post natürlich überflüssig.
Zuletzt geändert von EyDu am Donnerstag 10. Juli 2008, 22:48, insgesamt 1-mal geändert.
Benutzeravatar
wuf
User
Beiträge: 1419
Registriert: Sonntag 8. Juni 2003, 09:50

Donnerstag 10. Juli 2008, 21:25

Hallo derkai

Dieser Code-Abschnitt platziert 30 vertikale Reihen @ 10 Sechseck-Objekte nebeneinander auf die Canvas-Fläche 'spiel'. Die variable 'toggle' sorgt dafür das jede geradzahlige vertikale Reihe um eine halbe Sechseck-Höhe nach unten versetzt ist, damit die Wabenförmige Anordung entsteht..

Gruss wuf :wink:
Take it easy Mates!
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Donnerstag 10. Juli 2008, 22:06

das verstehe ich leider immer noch nicht.

es geht rein in die erste FOR Schleife, die wie Du schreibst die
Anzahl der vertikalen Reihen bestimmt. Vertikal heisst doch "untereinander", oder ?

Setze ich Columns auf 2 und Rows auf 10, dann erhalte ich
eine Reihe, die sich von oben nach unten aufbaut mit 10 Elementen
richtig ?
Danach eine zweite Reihe, ebenfalls von oben nach unten aufgebaut, richitg ?

Was ich dann nicht verstehe ist der Ablauf der beiden for Schleifen.

Erste Schleife :
- x erhält den Wert 1 beim ersten Durchlauf
- Weiter in Schleife 2

Zweite Schleife :
- y erhält den Wert eins beim ersten Durchlauf
- es wird ein Polygon erzeugt
Welche Daten werden für diesen ersten Schleifendurchlauf an
die Funktion übergeben ?
- spiel ?
- xpos = 10
- ypos = 10
- hex_point_list = sind das die Werte, die durch die Funktion
calculate_polygon_points errechnet wurden ?
- farbe = is klar

Ich habe noch viel mehr Fragen, aber immer hübsch der Reihe nach

BESTEN DANK

Kai
imac
20 Zoll
2,4 ghz
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Donnerstag 10. Juli 2008, 22:13

nur mal schnell noch ne Frage,

Du beschreibst es so, dass columns die Anzahl der
vertikalen Reihen darstellt und rows die Anzahl der
horizontalen REIHEN.

Nur für mein besseres Verständniss :

Ist es nicht eigentlich so, dass man die Anzahl der vertikalen Reihen
angibt und der Wert ROWS dann die Anzahl der Elemente in dieser
Reihe bestimmt ???

Nicht das das schlimm wäre, ich würde es nur gerne verstehen

Kai
Zuletzt geändert von derkai am Donnerstag 10. Juli 2008, 22:15, insgesamt 1-mal geändert.
imac
20 Zoll
2,4 ghz
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Donnerstag 10. Juli 2008, 22:14

wuf hat geschrieben:Hier ist die erste Variante der Code-Reduzierung: ...
Zeile 11-28 kann man wie folgt ersetzen:

Code: Alles auswählen

def calculate_polygon_points(l,x,y):
    """Berechne die Eckpunkte für ein Sechseck"""
    return x,y,x+l,y,x+1.5*l,y+.5*sqrt(3)*l,x+l,y+sqrt(3)*l,x,y+sqrt(3)*l,x-.5*l,y+0.5*sqrt(3)*l
Das "l" (= kleines L) sollte man vielleicht durch einen anderen Bezeichner ersetzen, damit man es nicht mit einer Eins verwechselt.
derkai
User
Beiträge: 169
Registriert: Montag 12. Mai 2008, 11:43

Donnerstag 10. Juli 2008, 22:40

ah bin ich doof ->
spiel ist meine GUI

d.h. mit dem Aufruf der Funktion wird an die Funktion selber,
also den Namen spiel_feld der Wert "spiel" weitergegeben ?

Kai
imac
20 Zoll
2,4 ghz
Benutzeravatar
wuf
User
Beiträge: 1419
Registriert: Sonntag 8. Juni 2003, 09:50

Donnerstag 10. Juli 2008, 23:15

Hallo numerix und derkai

Danke für eure Antworten. Ich habe hier noch die versprochene zweite Code reduzierende Variante basierend auf dem trigonometrischen Ansatz von 'EyDu'. Ich habe die Formel infolge meiner momentanen mathematischen Kenntnisse eventuell verunstaltet. Sorry. Aber 'EyDu' oder du 'numerix' sehen vermutlich mit einem Blick was ich hier zusammengewurstelt habe. :lol:

'numerix' ich werden dein Vorschlag für die Berechnung der Sechseck-Punkte noch austesten.

Hier der Code der zweiten Variante:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Skriptname derkai_05_02_02 (10.07.2008)

import Tkinter as tk
from math import sqrt,sin,cos,pi
from random import choice

def create_xyoffset(length):
    """Berechnet die XY-Versatzabstände"""

    N = 6
    poly_data = [(cos(2.0*pi/N*x)*length,sin(2.0*pi/N*x)*length) for x in range(N)]
    xa,ya = poly_data[0]
    xb,yb = poly_data[1]
    xc,yc = poly_data[5]

    return (length+(xa-xb),yb-yc)

def create_hex_polygon(spiel_feld,length,xpos,ypos,farbe):
    """Erzeugt das grafische Sechseck-Objekt"""

    N = 6
    poly_data = [(cos(2.0*pi/N*x)*length+xpos,sin(2.0*pi/N*x)*length+ypos) for x in range(N)]
    poly_obj = spiel_feld.create_polygon(poly_data,outline="black",fill=choice(farbe))

    return poly_obj


def main():
    #~~ Erzeugt das Hauptfenster
    master = tk.Tk()
    spiel = tk.Canvas(master, width=1024, height=768)
    spiel.pack()

    #~~ Sechseck Seitenlänge
    hex_laenge = 20.0 # Bestimmt die Sechseckgrösse
    #~~ Berechnung der XY-Versatzabstände für die Platzierung der Sechsecke
    xoffset,yoffset = create_xyoffset(hex_laenge)

    xpos = xorg = 30           # X Start-Koordinate
    ypos = yorg = 30           # Y Start-Koordinate
    columns = 30               # Anzahl vertikale Reihen
    rows = 10                  # Anzahl horizontale Reihen
    farbe = ("yellow","green","blue","red") # Zufalls-Farben

    #~~ Platziere den zweidimensionalen Sechseck-Array
    toggle = 0
    for x in xrange(columns):
        for y in xrange(rows):
            create_hex_polygon(spiel,hex_laenge,xpos,ypos,farbe)
            ypos += yoffset

        xpos += xoffset

        if not toggle:
            toggle = 1
            ypos = yorg + yoffset/2.0
        else:
            toggle = 0
            ypos = yorg

    master.mainloop()

main()
Ich werde noch für alle Varianten einen Geschwindigkeitstest durchführen.

Gruss und gute Nacht wuf :wink:
Take it easy Mates!
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 10. Juli 2008, 23:35

Du könntest das Erzeugen der Sechsecke noch in eine Funktion auslagern, dann musst du die LC nur einmal schreiben. Auch der Erstellen des Spielfeldes könnte eine eigene Funktion spendiert werden.

Wenn du jetzt noch die Namen der Konstanten in Großbuchstaben schreibst und zwischen den Parametern konsequent ein Leerzeichen lässt, dann sieht der Code gar nicht mal so schlecht aus! Man könnte sich jetzt natürlich noch überlegen, ob man das nicht alles sinnvoll in eine Klasse packen könnte.

Warum hat "create_hex_polygon" eigentlich eine Rückgabewert, so wie ich es sehe, wird dieser niemals verwendet.

Und noch eine kleine Anmerkung:
rows = Zeilen
columns = Spalten

;-)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Freitag 11. Juli 2008, 07:21

EyDu hat geschrieben:Warum hat "create_hex_polygon" eigentlich eine Rückgabewert, so wie ich es sehe, wird dieser niemals verwendet.
Dieser Rückgabewert ist ja die ItemID des auf dem Canvas erzeugten Sechsecks. Evtl. könnte es sinnvoll sein, diese ID gemeinsam mit anderen Eigenschaften des Sechsecks in einem Sechseck-Objekt zu kapseln, um über diese ID dann später Änderungen an der sichtbaren Gestalt des Sechsecks vornehmen zu können ohne ein neues Sechseck drüberzeichnen zu müssen (wenn sich z.B. die Farbe ändern soll).

@wuf: Den Teil

Code: Alles auswählen

  N = 6
    poly_data = [(cos(2.0*pi/N*x)*length,sin(2.0*pi/N*x)*length) for x in range(N)] 
Würde ich persönlich ersetzen durch:

Code: Alles auswählen

    poly_data = [(cos(pi/3*x)*length,sin(pi/3*x)*length) for x in range(6)] 
Benutzeravatar
wuf
User
Beiträge: 1419
Registriert: Sonntag 8. Juni 2003, 09:50

Freitag 11. Juli 2008, 16:06

Hallo derkai

Zuerst mal die Beantwortung deiner Fragen zu Post vom Do Jul 10, 2008 23:06
(Sind teilweise schon in den nächsten Posts beantwortet worden)

derkai hat geschrieben:Vertikal heisst doch "untereinander", oder ?
Sorry für meine schlechte Wortwahl.

vertikal = column = Spalte
horizontal = row = Zeile
Wir verwenden für das weitere Vorgehen die deutschen Namen.
derkai hat geschrieben:Setze ich Columns auf 2 und Rows auf 10, dann erhalte ich eine Reihe, die sich von oben nach unten aufbaut mit 10 Elementen
richtig ?
Es gibt zwei Spalten mit je 10 Sechseck-Objekte. Die obere Anfangsposition ist bei der zweiten Spalte um eine halbe Sechseck-Höhe nach unten versetzt.
derkai hat geschrieben:Welche Daten werden für diesen ersten Schleifendurchlauf an
die Funktion übergeben ?
- spiel ?
- xpos = 10
- ypos = 10
- hex_point_list = sind das die Werte, die durch die Funktion
calculate_polygon_points errechnet wurden ?

spiel = spiel_feld = Canvas-Objekt-Referenz
Sorry für die Diskrepanz 'spiel' <-> 'spiel_feld'. Von jetzt an ersetzen wir den Namen 'spiel' durch 'spiel_feld'.
'hex_point_list' -> Deine Feststellung ist richtig. Das ist eine Liste mit den errechneten Koordinaten-Punkten de Sechseckes [x1,y1........x6,y6]

Die trigonometrischen Berechnungs-Variante von 'EyDu' liefert diese Koordinaten-Punkte auch in einer Liste bei welcher jeder xy-Punkt in ein Tuple gepackt ist [(x1,y1),(x2,y2)......(x6,y6)]. Offenbar akzeptiert die Canvas-Methode 'create_polygon' beide Listen-Varianten.
Take it easy Mates!
Benutzeravatar
wuf
User
Beiträge: 1419
Registriert: Sonntag 8. Juni 2003, 09:50

Freitag 11. Juli 2008, 16:30

Hallo derkai

Zuerst mal die Beantwortung deiner Fragen zu Post vom Do Jul 10, 2008 23:13
derkai hat geschrieben:Ist es nicht eigentlich so, dass man die Anzahl der vertikalen Reihen
angibt und der Wert ROWS dann die Anzahl der Elemente in dieser
Reihe bestimmt ???
Stimmt, du kannst Sechsecke in einer einzelnen Spalte als Elemente bezeichnen. Sobald du mehrere Spalten nebeneinander hast können die horizontal in einer Reihe liegenden Elemente als 'Zeile' bezeichnet werden.

OK. derkai ich hoffe deine Fragen verständlich beantwortet zu haben.

Konntest du mit den bestehenden Code-Snippets.etwas herumspielen? Speziell mit den Variablen 'laenge', 'columns' neu 'spalten' und 'rows' neu 'zeilen'?

Hast du auch die verschieden Varianten zur Berechnung der Koordinaten-Punkte des Sechsecks angeschaut und versucht zu verstehen. Übrigens wie gefällt dir die Geschwindigkeit des Grafikaufbaus, also die Platzierung der Sechsecke auf der Canvas-Fläche gegenüber dem frog-Modul?

Hast du noch weitere Fragen?

Gruss wuf :wink:
Take it easy Mates!
Antworten