button in for-schleife mit verschiedenen variablen-namen erz

Fragen zu Tkinter.
Antworten
php_guru
User
Beiträge: 13
Registriert: Dienstag 29. April 2014, 14:22

Hallo zusammen.
Folgendes Problem: Ich habe mehrere Buttons zum löschen. Diese werden in einer Schleife erzeugt.
Das Problem ist nun, dass jeder Dieser Buttons self.buttonDel heisst und deswegen immer nur der letzt wert(i) per command an "def delUser(id):" übergeben wird.
Ist ja klar wieso, weil ich self.buttonDel jedes mal überschreibe.
Wie kann ich in einer Schleife die variablen: self.buttonDel1 , self.buttonDel2 ect.. erzeugen.
self.buttonDel wäre gut ist aber nicht möglich (AttributeError).
Wäre sehr dankbar um Eure Mithilfe

Code: Alles auswählen

    def getUsers(self):
        self.res = db.execute("SELECT id,name,vorname,email FROM mitarbeiter")
        for i in self.res:
            self.mitarb = Label( self.root )
            w = []
            zaehler = 0
            
            for x in i:
                w.append(x)
                if(zaehler<len(i)-1):
                    w.append(',')
                zaehler+=1
                
            self.mitarb.config(text= w)
            self.mitarb.pack()
            self.buttonDel = Button(self.root,text='Loesche User '+str(i[0]),command= lambda: delUser(i[0]) )
            self.buttonDel.pack()
       
        def delUser(id):
            print(str(id))
php_guru
User
Beiträge: 13
Registriert: Dienstag 29. April 2014, 14:22

Habs gelöst:
Lösung: command= lambda i=i: self.delUser(i):
Code:

Code: Alles auswählen

    def getUsers(self):
        self.res = db.execute("SELECT id,name,vorname,email FROM mitarbeiter")
        for i in self.res:
            self.mitarb = Label( self.root )
            w = []
            zaehler = 0
            
            for x in i:
                w.append(x)
                if(zaehler<len(i)-1):
                    w.append(',')
                zaehler+=1
                
            self.mitarb.config(text= w)
            self.mitarb.pack()
            self.buttonDel = Button(self.root,text='Loesche User '+str(i[0]),command= lambda i=i: self.delUser(i))
            self.buttonDel.pack()

    def delUser(self,id):
        print(str(id[0]))
BlackJack

@php_guru: Ein paar Anmerkungen:

Da wird viel zu viel unnötigerweise an das Objekt gebunden was eigentlich bloss lokale, temporäre Werte in der Methode sind. In der `getUsers()` müsste man keinen einzigen Wert an das Objekt binden. Umgekehrt frage ich mich wo `db` her kommt. Man sollte in Funktionen und Methoden nichts verwenden was nicht als Argument übergeben wurde. Ausgenommen natürlich Konstanten.

Tkinter wird üblicherweise beim Importieren nach `tk` umbenannt. Dann braucht man nicht so viel tippen. Sternchenimporte sollte man vermeiden. Im Fall von Tkinter holt man sich da über 190 Namen in das Modul, von denen man nur einen kleinen Bruchteil tatsächlich verwendet. Der Rest müllt einfach nur den Namensraum zu.

Die Namen halten sich nicht an den Style Guide for Python Code.

Abkürzungen bei Namen sollte man vermeiden. Es geht nicht darum Buchstaben zu sparen sondern dem Leser zu vermitteln wofür die Werte hinter den Namen stehen. `res` statt `result`, oder `mitarb` statt `mitarbeiter` muss doch echt nicht sein. Einbuchstabige Namen sind in der Regel auch eine schlechte Idee wenn sie nicht sehr begrenzt sind in ihrer Verwendung, zum Beispiel innerhalb eines einzigen Ausdrucks. Und `i` in einer Schleife für etwas anderes als eine ganze Zahl zu verwenden, verstösst extrem gegen die Erwartungen der meisten Programmierer.

Das was da mit `w`, `x`, `zaehler`, und der Schleife angestellt wird, sieht sehr umständlich aus. Kann es sein, dass Du hier einfach die `join()`-Methode verwenden wolltest‽

Anstelle von dem ``lambda`` mit dem Default-Wert würde man heutzutage eher `functools.partial()` verwenden.

Das `id`-Argument bei `delUser()` ist falsch benannt, denn da wird ja nicht nur die ID sondern der gesamte Datensatz als Sequenz übergeben.

Ich komme dann bei ungefähr so etwas heraus (ungetestet):

Code: Alles auswählen

from functools import partial

# ...

    def get_users(self):
        rows = self.db.execute('SELECT id,name,vorname,email FROM mitarbeiter')
        for row in rows:
            tk.Label(self.root, text=', '.join(map(str, row))).pack()
            tk.Button(
                self.root,
                text='Loesche User {0}'.format(row[0]),
                command=partial(self.delete_user, row)
            ).pack()
 
    def delete_user(self, row):
        print(row[0])
php_guru
User
Beiträge: 13
Registriert: Dienstag 29. April 2014, 14:22

@BlackJack:

Danke für deine Hilfe: Ich habe den Code probiert und erhalte folgende Fehlermeldung:
tk.Label(self.root, text=', '.join(map(str, row))).pack()
NameError: name 'tk' is not defined
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dir fehlt ein ``import tkinter as tk`` am Anfang des Programms. Du hast Tk bei dir mittels *-Import importiert, die gezeigte Variante ist die bessere Alternative. Wöhne dir *-Importe gleich wieder ab, die müllen dir den ganzen Namensraum zu, überschreiben leicht vorhandene Namen und machen das Herausfinden der Herkunft von Namen nur unnötig schwierig.
Das Leben ist wie ein Tennisball.
php_guru
User
Beiträge: 13
Registriert: Dienstag 29. April 2014, 14:22

@EyDu:
Bitte um ein Beispiel
mit der Variante import tkinter as tk
z.B. für das:

Code: Alles auswählen

from tkinter import *
class Beispiel(object):
    def __init__(self):
        self.root = Tk()
        
        self.eingabe_user = Entry(self.root)
        self.eingabe_user.pack()
        
        self.button_user_eintragen = Button(self.root,text='User eintragen')
        self.button_user_eintragen.pack()
        
        self.root.mainloop()
        
Beispiel() 
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

php_guru hat geschrieben:@EyDu:
Bitte um ein Beispiel
mit der Variante import tkinter as tk
z.B. für das:
...
EyDu hat Dir doch schon explizit geschrieben, *wie* Du den Import schreiben musst :!:

Du musst dann noch lediglich die Namen aus dem Modul mit dem definierten Alias als Präfix ergänzen - das kann doch nicht so schwer sein ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
php_guru
User
Beiträge: 13
Registriert: Dienstag 29. April 2014, 14:22

@ Hyperion

Ich hatte anfangs Fehlermeldungen aber wie unten gehts:
Kann mir jemand ein gutes Python-Buch vorschlagen?

Code: Alles auswählen

import tkinter as tk
class Beispiel(object):
    def __init__(self):
        tk.Entry().pack()
        tk.Button(text='User eintragen').pack()
        tk.mainloop()
        
Beispiel()   
Zuletzt geändert von php_guru am Samstag 3. Mai 2014, 18:28, insgesamt 1-mal geändert.
php_guru
User
Beiträge: 13
Registriert: Dienstag 29. April 2014, 14:22

wie erstellt man mit bei import tkinter as tk
den fenstertitel und die geometry?

Code: Alles auswählen

tk.titel('userverwaltung'), tk.geometry('500x500')
wie füllt man ein neues Fenster: tk.Toplevel() mit Inhalten (Label, Buttons ect..)?

Ich danke Euch für die Hilfe.
Es ist schwer für mich, wenn man sich schlechte Sachen aus YouTube aneignet :(
Wäre sonst wirklich froh um einen Tipp: Tutorials oder Bücher..
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi php_guru

Code: Alles auswählen

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

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk

app_win = tk.Tk()
app_win.title('userverwaltung')
app_win.geometry('500x500')

app_win.mainloop()
Hier zwei hilfreiche Seiten aus dem Internet:
http://effbot.org/tkinterbook/
http://infohost.nmt.edu/tcc/help/pubs/t ... index.html

Gruss wuf :wink:
Take it easy Mates!
Antworten