mainloop(): Anfangszustand überschreiben

Fragen zu Tkinter.
Antworten
Hikaru15
User
Beiträge: 7
Registriert: Sonntag 27. November 2011, 18:28

Wenn ich mein Programm (ohne class) laufen lasse, beginnt die "mainloop" ganz oben, d.h. der Anfangszustand wird bei jedem Durchlauf wiederhergestellt, Änderungen des unteren Programmteils werden daher überschrieben.
Was kann ich tun?
BlackJack

@Hikaru15: Das Problem so beschreiben das man es verstehen kann!? ;-)
Hikaru15
User
Beiträge: 7
Registriert: Sonntag 27. November 2011, 18:28

Zuerst Danke für die schnelle Antwort.
Also Ich versuch's nochmal:
In dem Programm 'zeichne' ich ein canvas und darin mit create_rectangle und create_line ein Spielfeld (etwa wie Schach). Per Mausklick will ich nun die (background) Farben einzelner Felder ändern.
Das Klicken funktioniert, auch die Farben, in einer Liste abgelegt, werden wunschgemäß geändert. Aber offenbar werden diese Werte - von mainloop() - wieder in den Anfangszustand zurückgesetzt.
(Zur Not kann ich aber auch ein Demo-Programm posten.)
BlackJack

@Hikaru15: Das wirst Du wohl müssen, denn die Hauptschleife macht so etwas nicht einfach von sich aus.
Hikaru15
User
Beiträge: 7
Registriert: Sonntag 27. November 2011, 18:28

Hier meine Minimalversion des Programms, bei dem die Variable colour durch mainloop() immer wieder auf [gelb,gelb] zurückgesetzt wird.

Code: Alles auswählen

# Minimal-Version

x0, x1, y0, y1 = 0, 0, 0, 0      # Positions mouseclick
first   = True
coursor = [0, 0]


# Das folgende Statement soll nur einmal ausgeführt werden!
# =====================================
if first: colour = ["yellow", "yellow"]
first = False


from tkinter import *

frame = Tk()

side_x = 1100
side_y = 800
c = Canvas(master=frame, width=side_x, height=side_y)
c.pack(side=LEFT)

sudoku = c.create_rectangle(0, 0, 500, 500, fill='white')

c.create_rectangle(100, 100, 200, 200, fill=colour[0])
c.create_rectangle(200, 100, 300, 200, fill=colour[1])

c.create_line(100, 100, 100, 200, width=2) #
c.create_line(200, 100, 200, 200, width=2) #
c.create_line(300, 100, 300, 200, width=2)
c.create_line(100, 100, 300, 100, width=2)
c.create_line(100, 200, 300, 200, width=2)

def mouseclick(event):
    global x0, x1, y0, y1
    global first
    global coursor
    x = event.x
    y = event.y
    if x < 100 or x > 300 or y < 100 or y > 200:
        print ("clicked outside of the Field!")
        return
    # Bestimme die Koordinaten i und j im Sudoku
    if x < 200:
        print("clicked left")
        colour[0] = "red"
    else:
        print("clicked right")
        colour[1] = "red"
    #
#

#frame.bind("<KeyPress>", keyclick)
frame.bind("<Button-1>", mouseclick)
frame.mainloop()

BlackJack

@Hikaru15: Das stimmt doch gar nicht. Wenn Du Dir zum Beispiel am Anfang der Funktion `colour` mal ausgeben lassen würdest, dann könnte man das auch sehen das in der Liste 'yellow' durch 'red' ersetzt wird, wenn man an die entsprechenden Stellen auf dem Canvas klickt.

Alles auf Modulebene was nicht in einer Schleife steht wird nur einmal ausgeführt. `first` macht also keinen Sinn und kann ersatzlos gestrichen werden.

Insgesamt sieht der Quelltext so aus, als wenn Du erst einmal die Grundlagen bis inklusive objektorientierter Programmierung lernen solltest, bevor Du Dich an GUI-Programmierung setzt.

Konkrete Anmerkungen: Auf Modulebene schreibt man üblicherweise nur Definitionen von Konstanten, Funktionen, und Klassen. Das Hauptprogramm steht dann in einer `main()`-Funktion, die durch folgendes Idiom aufgerufen wird:

Code: Alles auswählen

if __name__ == '__main__':
    main()
``global`` hat in ordentlichen Programmen nichts zu suchen — braucht man auch nicht wenn man keine Variablen auf Modulebene hat.

Der Style Guide for Python Code empfiehlt auch bei Blöcken die nur aus einer Zeile bestehen, diese Zeile eingerückt in eine eigene Zeile zu schreiben.

Importe stehen üblicherweise am Anfang eines Moduls, damit man die Übersicht behält wovon ein Modul abhängt, ohne dass man es sich komplett durchlesen muss. Sternchen-Importe sollte man vermeiden, damit nachvollziehbar bleibt wo genau Namen her kommen, und man sich keine Kollisionen einhandelt. Die Tk-Schnittstelle wird oft als `tk` importiert: ``import tkinter as tk``.
Hikaru15
User
Beiträge: 7
Registriert: Sonntag 27. November 2011, 18:28

1. Absatz: Ja, nach dem Mausklick wird colour richtig gesetzt, aber auf dem Bildschirm bleiben die 2 Felder gelb.
2. Absatz: first führte ich aus Verzweifelung ein.
3. Absatz: Meine Schwachstelle. Aber nach sehr vielem Lesen und vielen Versuchen ist der Frust groß. Vielleicht bin ich da zu dumm.
4. Absatz: Habe gestern den thread über global in "Allgemeine Fragen" gelesen. Nehme ich mir zu Herzen.
5 . Absatz: Einrücken eines Einzeilers fand ich nicht so schön, aber OK, ist schlechter Stil.
5. Absatz: Ebenfalls aus Verzweifelung habe ich das Import-Statement hinter die Zuweisung an colour gesetzt.
6. Absatz: Hatte ich auch schon mal gelesen, aus Schlamperei oder Bequemlichkeit noch nicht umgesetzt. Werde mich bessern.

Aber wo kann der Fehler stecken?

Jetzt gehe ich schlafen.
Für Deine Antwort erstmal besten Dank!
BlackJack

@Hikaru15: Im Grunde ist da kein Fehler in dem Sinne. Das zuweisen eines Elements in einer Liste hat keine Auswirkungen die über diese Zuweisung hinaus gehen. Die Liste weiss nichts von dem Rechteck und das Rechteck weiss nichts von der Liste. Wenn Du die Farbe von so einem Rechteck ändern willst, dann musst Du das explizit mit der dafür vorgesehenen API machen. Also in diesem Fall mit der `Canvas.itemconfig()`-Methode. Mehr Infos: http://effbot.org/tkinterbook/canvas.htm

Ich würde auch nicht selber anfangen mit Koordinaten herum zu rechnen um heraus zu finden welches Rechteck angeklickt wurde, sondern an jedes Rechteck eine Rückruffunktion für das anklicken binden.
Hikaru15
User
Beiträge: 7
Registriert: Sonntag 27. November 2011, 18:28

Danke für die Hilfe und den Link zu effbot.
In meinem 'Weigend' fehlt jeder Hinweis und Kommentar zu Canvas.itemconfig.
Jetzt hab ich wieder Hoffnung, dass ich weiterkomme.
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo Hikaru15

schau mal da http://infohost.nmt.edu/tcc/help/pubs/t ... index.html
Gruss
Peter
Antworten