"andere" buttons inerhalb eines GRID ansprechen/verändern

Fragen zu Tkinter.
Antworten
msmn
User
Beiträge: 35
Registriert: Samstag 13. Juli 2019, 07:15

stelle hier jetzt mal meinen (vereinfachten) Code hier herein...
(habe dabei versucht vieles von den Befehlsabfolgen bei den jeweils gedrückten Buttons, etc..rauszuschmeissen, sodas dieser übersichtlicher/lesbarer wird).
Um was es geht: ich möchte mit den Buttons zB unterschiedlichste Lichter/Lämpchen auf meiner Modellbahnanlage mittels Raspberry Pi und GPIOs sowie MCP23017 ansteuern....
...und natürlich sollte der eine oder andere Button dann auch auf Wunsch "mehrere" Lämpchen auf einmal schalten (also zB die Gebäude-Lichter in einem ganzen Strassenzug)

was ich dazu gerne hätte, ist dass zB bei Betätigung des Buttons "links oben"....einige/alle anderen Buttons "ihren Zustand optisch wechseln" (und dann natürlich auch hinterlegte Befehlsfolgen ablaufen)

ich hoffe, dies hilft zum besseren Verständnis meines Problems....sorry, dass ich Euch so bemühe.

Code: Alles auswählen

from tkinter import * 
from functools import partial
import time
import sys

########Definition der Variablen
#listenelemente_max_spalten=3 
listenelemente_max_zeilen=7
position_dir={'Start':0}  

matrixname= 'Lichtermatrix'
fenster_max_spalten=5         # Spalten(in jeder Reihe)
fenster_max_reihen=listenelemente_max_zeilen//fenster_max_spalten
if (listenelemente_max_zeilen%fenster_max_spalten)>0:
    fenster_max_reihen=fenster_max_reihen + 1
fenster_width=12
fenster_height=3

#####################################
########Definition des Listenarrays
hauptliste = [["0=Position","1=Bezeichnung",      "2=Adresse","3=Ein/Aus","4=MCS23017-Hex-Adresse","5=MCS-Bank","6=MCS-Adresse"]]
hauptliste =hauptliste + [[ 1,"Alle Lichter","ALLE","E/A(0,1)",0,"leer",0]]
#                        Pos0, Pos1     ,      Pos2,  Pos3, Pos4, Pos5, P6
hauptliste =hauptliste + [[ 2,"Licht  2",        29,     0,    0,  "A", 0]]
hauptliste =hauptliste + [[ 3,"Licht  3",        31,     1,    0,  "A", 0]]
hauptliste =hauptliste + [[ 4,"Licht  4",        33,     0,    0,  "A", 0]]
for ii in range (4,listenelemente_max_zeilen):
    hauptliste =hauptliste +[[ii+1,"Licht, Lampe."+str(ii+1).zfill(3),37,0,0,"",0]]

def bei_mausklick(geklickt): 
    if hauptliste[geklickt][3]==1:
        print ("mach was EIN")
    elif hauptliste[geklickt][3]==0:
        print ("mach was AUS")
            
def toggle1(button):
    geklickt=position_dir[str(button)]
    if geklickt == 1:
        button.flash()                      #damit blinkt der Button kurz
        print ("270 hier sollte dann ALLE Lichter geschalten werden...und alle Buttons entsprechend zB die Farbe ändern")
    elif geklickt <= listenelemente_max_zeilen:
        button.state = not button.state
        zw_text = hauptliste[geklickt][1]+" "+str(hauptliste[geklickt][2])+" "+str(hauptliste[geklickt][4])+" "+hauptliste[geklickt][5]+" "+str(hauptliste[geklickt][6])
        if button.state == 1:
            button['text'] = zw_text + " AUS"
            button.config (bg='brown')  
            hauptliste[geklickt][3]=0
        if button.state == 0: 
            button['text'] = zw_text + " EIN"
            button.config (bg='light green') # von MO
            hauptliste[geklickt][3]=1
        bei_mausklick(geklickt)           
    else:
        print ("292 ########## Element nicht vorhanden (ausserhalb der vordefinierten Parameter!):")

def new1_btn(state,reihe,spalte,tot,position):
    btn = Button() 
    btn.config(width=fenster_width, height=fenster_height,activebackground="yellow",activeforeground="black")
    position[str(btn)]=tot+1
    zw_text="FEHLT!"
    if tot < listenelemente_max_zeilen:
        zw_text=hauptliste[tot+1][1]+" " +str(hauptliste[tot+1][2])+" "+str(hauptliste[tot+1][4])+" "+hauptliste[tot+1][5]+" "+str(hauptliste[tot+1][6])
        if   hauptliste[tot+1][3]==0: btn.config (bg='brown')
        elif hauptliste[tot+1][3]==1: btn.config (bg='light green')
        else:
            btn.config (bg='#E1D1A9')               # farbe für den "Alles-Button"
    else:
        btn.state='disabled'               # damit wird Button ausgegraut
    btn.config (wraplength=fenster_width*8)        #das ist scheinbar in Pixel!?
    btn.config(text=zw_text,command = partial(toggle1, btn))  
    btn.state = bool(state)
    try:
        if hauptliste[tot+1][3]==1: btn.state = not btn.state # damit bei Erstaufbau die Buttondefinition (0/1) richtig ist
    except: print(" 99 ist ausserhalb!...also kein Problem")
    btn.grid(row=reihe,column=spalte,padx=4,pady=4)
    return btn
#####################################
    
########Definition des Fensters
main0= Tk() 
main0.title(matrixname)

for x in range (0,fenster_max_reihen):
    for y in range (0,fenster_max_spalten):
        z=x*fenster_max_spalten+y
        new1_btn(main0,x,y,z,position_dir)

main0.mainloop()
sys.exit()
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast "btn". Benutz das doch, statt darum unnoetigerweise str(btn) aufzurufen. Was auch immer du dann mit position machen kannst und willst, du hast als Schluessel die Buttons und kannst die auch ansprechen dadurch.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@msmn: Sternchenimporte sind schlecht. Normalerweise importiert man `import tkinter as tk` und spricht alle tk-Namen per tk.xyz an.

Die Namensgebung ist nicht optimal. Irgendwelche Zahlen an Variablennamen zu hängen, ist meist keine gute Idee, was soll `main0` denn sein? Oder toggle1? Oder new1?
`hauptliste` list zum einen ein schlechter Name, gibt es auch noch neben-Listen? Zum anderen sollte keine Datentypen in Namen vorkommen. Der Inhalt ist auch schlecht. Was soll denn das erste Element der Liste? Der Kommentar was die Einträge bedeuten? Statt Listen in Listen zu packen, wo jeder der 7 Elemente eine bestimmte Bedeutung hat, solltest Du eine passendere Datenstruktur wählen, Wörterbuch, NamedTuple oder spezielle Klasse. Damit wird auch der Rest des Codes lesbarer.

Nach jedem Doppelpunkt der einen Block einleitet, wird eine neue Zeile angefangen. Aller Code auf Modulebene, der keine Funktionsdefinition oder Konstante ist, sollte in eine Funktion wandern.

In new1_btn übergibst Du statt `state` `main0`. Das macht so keinen Sinn. position ist eine seltsame Struktur. Statt den Index der Stringrepräsentation der Buttonobjekte in einem Wörterbuch zu speichern, solltest Du die gesamte Information, die Du brauchst, in einem Button-Objekt speichern und das benutzen.

Statt über Reihe und Spalte zu iterieren, wäre es einfacher über alle Elemente der Hauptliste zu iterieren und deren Index in Reihe und Spalte umzurechnen.
msmn
User
Beiträge: 35
Registriert: Samstag 13. Juli 2019, 07:15

@_deets_: Danke, habe schon die "str" weggenommen....

@Sirius3: ebenfalls danke....werde Deine Tipps einen nach den anderen umsetzen.
Du schreibst jedoch auch: "...Statt den Index der Stringrepräsentation der Buttonobjekte in einem Wörterbuch zu speichern, solltest Du die gesamte Information, die Du brauchst, in einem Button-Objekt speichern und das benutzen..:"
ich denke, genau das ist der Punkt...kannst Du bitte erklären, wie...."die gesamte Information in einem Button-Objekt gespeichert und benutzt werden kann"?
Danke

msmn
Antworten