Seite 1 von 1

Denkfehler bei ButtonArray

Verfasst: Mittwoch 30. Oktober 2019, 10:31
von MissMapeL
Hallo,
ich beginne gerade erst mit Python und sthe vermutlich z.Zt. 'auf dem Verständnis-Schlauch'.
Warum werden beim Clicken nicht die geklickten Buttons sondern immer der in der letzten Spalte rot?

Wäre für eine Klärung SUPER-dankbar.

from tkinter import *

class App:
def __init__(self, master):
frame=Frame(root)
frame.grid(row=0,column=0)

xmax = 3
ymax = 4
self.btn= [[0 for y in range(ymax)]]*3
for x in range(xmax):
for y in range(ymax):
self.btn[x][y] = Button(frame,command= lambda x1=x, y1=y: self.color_change(x1,y1), height=10, width=25)
self.btn[x][y].grid(column=x, row=y) #frame.pack()


def color_change(self,x,y):
self.btn[x][y].config(bg="red")
print(x,y)

root = Tk()
app = App(root)
root.mainloop()

Re: Denkfehler bei ButtonArray

Verfasst: Mittwoch 30. Oktober 2019, 11:51
von Sirius3
Sternchenimport sind böse, weil man sich da unkontrolliert hunderte Namen in den eigenen Namensraum schaufelt. Tkinter wird üblicherweise als `import tkinter as tk` eingebunden und alle Namen per tk.xy angesprochen.
Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 2 und mal 3 oder 5.
In Python erzeugt man keine Listen mit Dummy-Werten und füllt sie danach. `0` ist auch ein sehr schlechter Dummywert: None sagt, dass es (noch) kein Objekt gibt. Da liegt auch das Problem, dass Du keine Liste mit drei Unterlisten hast, sondern die Liste enthält drei mal (siehe *3), die selbe Liste, so dass nur die Buttons der letzten Reihe übrigbleiben, der Rest wird in der for-Schleife überschrieben (übrigens die innere Listcomprehension ist unötig, weil man bei unveränderlichen Objekten auch [0]*ymax schreiben könnte). Aber wie schon geschreiben: macht man nicht.
Statt `lambda` benutzt man `partial`. Keine Abkürzungen benutzen.

Die letzten drei Zeilen gehören auch in eine Funktion, die man üblicherweise `main` nennt. Das verhindert, dass man aus Versehen globale Variablen benutzt (wie in App.__init__).

Code: Alles auswählen

import tkinter as tk
from functools import partial

class App:
    COLUMN_MAX = 3
    ROW_MAX = 4
    def __init__(self, master):
        frame = tk.Frame(master)
        frame.grid(row=0,column=0)
        self.buttons = []
        for column in range(self.COLUMN_MAX):
            buttons = []
            for row in range(self.ROW_MAX):
                button = tk.Button(frame, command=partial(self.color_change, column, row), height=10, width=25)
                button.grid(column=column, row=row)
                buttons.append(button)
            self.buttons.append(buttons)

    def color_change(self, column, row):
        self.buttons[column][row]['bg'] = 'red'
        print(column, row)

def main():
    root = tk.Tk()
    app = App(root)
    root.mainloop()
    
if __name__ == '__main__':
    main()

Re: Denkfehler bei ButtonArray

Verfasst: Mittwoch 30. Oktober 2019, 11:54
von /me
Um noch mal ein Beispiel zu geben was bei deinem `self.btn= [[0 for y in range(ymax)]]*3` eigentlich passiert.

Code: Alles auswählen

>>> ymax = 4
>>> btn = [[0 for y in range(ymax)]] * 3
>>> btn
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> btn[1][2] = 3
>>> btn
[[0, 0, 3, 0], [0, 0, 3, 0], [0, 0, 3, 0]]
(Ich wollte ja ausführlicher antworten, aber das hatte Sirius3 dann schon erledigt.)

Re: Denkfehler bei ButtonArray

Verfasst: Mittwoch 30. Oktober 2019, 11:59
von __blackjack__
@MissMapeL: Noch eine Kleinigkeit: Listen sind keine Arrays, man sollte sie deswegen auch nicht so nennen. Es gibt in Python auch Arrays, damit sind dann meistens die Datentypen mit diesem Namen aus dem Numpy-Package gemeint.

Re: Denkfehler bei ButtonArray

Verfasst: Mittwoch 30. Oktober 2019, 17:07
von MissMapeL
Vielen Dank für die schnellen Antworten.
Ich werde mir die Kritik ( 4 Leerzeichen pro Ebene, ...) zu Herzen nehmen und gelobe sofortige Besserung.
Bisher habe ich vor allem C# und VB programmiert. Aus diesen Sprachen habe ich die Idee der Arrays übernommen.

Auf zum nächsten Veruch...
Liebe Grüße und Danke an alle!!!