command mit OOP funktioniert nicht

Fragen zu Tkinter.
Antworten
reiwe3
User
Beiträge: 12
Registriert: Samstag 21. August 2021, 14:46

Hallo Experten,
es geht um GUI mit tkinter und OOP.
Ohne OOP habe ich schon mehrer GUIs gemacht, da funktioniert es.
Mit OOP habe ich Schwierigkeiten mit dem command.
Hier die Zeile:
neuein_button=tk.Button(self.frame2,text="Neue ",font=self.my_font,command=self.start).grid(row=3,column=4,padx=5,pady=5,sticky=tk.E)
def start(self):
pass
print("hallo, hier geht es weiter!")

und nun die Fehlermeldung:
neuein_button=tk.Button(self.frame2,text="Neue ",font=self.my_font,command=self.start).grid(row=3,column=4,padx=5,pady=5,sticky=tk.E)
AttributeError: 'Eingeben' object has no attribute 'start'
Das verstehe ich, aber wie geht das richtig.
Wenn ich das self weglasse also command=start mache kommt die Meldung:
return self.func(*args)
TypeError: start() missing 1 required positional argument: 'self'
Auch das ist klar, aber wie geht es nun richtig ?

Mein Programm:
import tkinter as tk
from tkinter import ttk

class Eingeben():
pass
def __init__(self, master):
pass
self.master = master
self.master.geometry("600x300")
self.master.title("RÜCKNAHMEN / Eingabe")

self.wel_frame= tk.Frame(master,bd=20,)
self.wel_frame.grid(row=0, column=2,padx=5,pady=5,)
self.my_font=("Arial",14)

start_label=tk.Label(self.wel_frame, text='Rot',font=self.my_font,fg="red").grid(row=1,column=0,pady=5,padx=5,sticky=tk.W)
weiter_label=tk.Label(self.wel_frame,text="Blau",font=self.my_font,fg="blue" ).grid(row=2,column=0,padx=5,pady=5,sticky=tk.W)
next2_label=tk.Label(self.wel_frame,text="Gruen",font=self.my_font,fg="green").grid(row=3,column=0,padx=5,pady=5,sticky=tk.W)
next3_label=tk.Label(self.wel_frame,text="Stueckzahl",font=self.my_font).grid(row=0,column=1,padx=5,pady=5,sticky=tk.W)
next4_label=tk.Label(self.wel_frame,text=" Preis/€ ",font=self.my_font).grid(row=0,column=2,padx=5,pady=5,sticky=tk.W)
next5_label=tk.Label(self.wel_frame,text=" noch",font=self.my_font).grid(row=1,column=2,padx=5,pady=5,sticky=tk.W)
next6_label=tk.Label(self.wel_frame,text="so-so",font=self.my_font).grid(row=2,column=2,padx=5,pady=5,sticky=tk.W)
next8_label=tk.Label(self.wel_frame,text=" Name",font=self.my_font).grid(row=6,column=0,padx=5,pady=5,sticky=tk.W)

rotstck_entry=tk.Entry(self.wel_frame,bg="white").grid(row=1,column=1,padx=5,pady=5,sticky=tk.W)
blaustck_entry=tk.Entry(self.wel_frame,bg="white").grid(row=2,column=1,padx=5,pady=5,sticky=tk.W)
gruenstck_entry=tk.Entry(self.wel_frame,bg="white").grid(row=3,column=1,padx=5,pady=5,sticky=tk.W)
kdname_entry=tk.Entry(self.wel_frame,bg="white",font=self.my_font).grid(row=6,column=1,columnspan=3,padx=5,pady=5,sticky=tk.W)
rotprs_entry=tk.Entry(self.wel_frame,bg="white").grid(row=1,column=2,padx=5,pady=5,sticky=tk.W)
blauprs_entry=tk.Entry(self.wel_frame,bg="white").grid(row=2,column=2,padx=5,pady=5,sticky=tk.W)
gruenprs_entry=tk.Entry(self.wel_frame,bg="white").grid(row=3,column=2,padx=5,pady=5,sticky=tk.W)
meldung_label=tk.Label(self.wel_frame,text="Meldung",font=self.my_font).grid(row=7,column=0,padx=5,pady=5,sticky=tk.W)
meldg_label=tk.Label(self.wel_frame,text= " ",bg="white").grid(row=6,column=1,columnspan=2,padx=5,pady=5,sticky=tk.W)

self.frame2 = tk.Frame(master,bd=20,)
self.frame2.grid(row=0, column=4,padx=5,pady=5,)
weiter_button=tk.Button(self.frame2, text='Weiter',fg="red",font=self.my_font).grid(row=0,column=4,padx=5,pady=5,sticky=tk.E)
neuein_button=tk.Button(self.frame2,text="Neue ",font=self.my_font,command=start).grid(row=3,column=4,padx=5,pady=5,sticky=tk.E)
ende_button=tk.Button(self.frame2,text="ENDE ",font=self.my_font,command=self.master.destroy).grid(row=4,column=4,padx=5,pady=5,sticky=tk.E)


def start(self):
pass
print("hallo, hier geht es weiter!")

def main():
pass
root=tk.Tk()
app=Eingeben(root)
root.mainloop

if __name__ == "__main__":
main()


Sicher, das ist ohne OOP auch machbar, ich habe bisher wenig mit OOP gemacht, deshalb. Da es sich um den Anfang einer Simulation handelt, brauche ich die OOP für weiteres.
Danke für alle Hinweise!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Langsam aber sicher muss dir doch auch aufgefallen sein, dass den Code hier einfach einzukopieren dazu fuehrt, dass der komplett unlesbar ist. Und es code-Tags gibt, welche die Antworter auf deine Fragen auch nutzen. Bitte mach das auch. Denn so ist das nur Bleiwueste.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@reiwe3: Was sollen die ganzen unsinnigen ``pass``-Anweisungen in dem Code?

Was an der Fehlermeldung verstehst Du nicht? Warum glaubst Du `Eingeben` hätte eine `start()`-Methode? Woher weiss der Compiler was als Methode zur Klasse gehört und was eine einfache Funktion ist? Würdest Du Dich auch wundern, dass es keine `main()`-Methode auf `Eingeben`-Objekten gibt?

`Eingeben` ist als Name falsch. Klassen modellieren ”Dinge” im weitesten Sinne. Ein `Eingeben` ist kein Ding. Das ist eine Tätigkeit, also ein Name für eine Funktion oder Methode, aber nicht für eine Klasse.

`master` für das Argument von `Eingeben.__init__()` ist zu allgemein und `Eingeben` ist auch gar kein `Widget`, also ist der Name auch ein bisschen irreführend. `master` kann auch kein beliebiges Widget sein, es muss ein Fenster sein, also ein `Tk`- oder `Toplevel`-Objekt. Wobei die Aktion die das benötigt im Grunde sowieso nicht sein sollte — `geometry()` ist in aller Regel unnötig weil die Grösse durch den Inhalt des Fensters vorgegeben wird.

Namen sollten keine kryptischen Abkürzungen anthalten und auch nicht durchnummeriert werden. Man muss auch nicht alles an einen Namen binden. Und auch nicht alles was man an einen Namen bindet muss man auch an das Objekt binden, wenn das gar nicht zum Zustand gehört.

Es werden auch insgesamt 20 Namen an den Wert `None` gebunden, was keinen Sinn macht. Der Rückgabewert von `grid()` ist `None`!

Die Vorsilbe `my` mach keinen Sinn wenn es nicht auch `our` oder `their` gibt, gegen das sich das abgrenzen würde.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
reiwe3
User
Beiträge: 12
Registriert: Samstag 21. August 2021, 14:46

Hallo __deets__ ,
danke für die schnelle Antwort.
Ja mit der Bleiwueste da war ich zu schludrig - sorry ich werde mich bessern.
reiwe3
User
Beiträge: 12
Registriert: Samstag 21. August 2021, 14:46

Hallo __blackjack__ ,
danke für die schnelle Antwort!
Die pass Anweisungen nehme ich oft als Mass für das Einrücken,
dann nehme ich sie wieder raus, das habe ich da leider vergessen.
Dass Klassen "Dinge" modellieren ist mir noch nicht aufgefallen, aber jetzt sehe ich es richtig, ich darf
die Klasse nicht so benennen!
Die Namen habe ich vergeben weil ich sie noch benötige, aber es ist richtig ich hätte sie hier nicht gebraucht.
master war als fenster gedacht, aber es wird in dem Programm nur für die frames verwendet, das wäre, so sehe ich das jetzt nicht nötig, es wird also gar nicht gebraucht .
Ich habe mich missverstaendlich ausgedrueckt: ich verstehe die Fehlermeldungen.
Aber ich kann die richtige command-Anweisung nicht finden .. um beim Drücken des buttons zur Funktion zu kommen. ( es geht nicht: command = self.start was anderes finde ich nicht).
Vielen Dank für die vielen Hinweise ich überarbeite jetzt das Programm , wahrscheinlich ergibt sich der Fehler dann nicht mehr, sonst melde ich mich noch einmal.
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

@reiwe3 versuche mal die Fragen von @__blackjack__ für dich oder hier zu beantworten, dann sollte es klarer werden.
__blackjack__ hat geschrieben: Montag 21. Februar 2022, 17:26 Warum glaubst Du `Eingeben` hätte eine `start()`-Methode? Woher weiss der Compiler was als Methode zur Klasse gehört und was eine einfache Funktion ist? Würdest Du Dich auch wundern, dass es keine `main()`-Methode auf `Eingeben`-Objekten gibt?
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
reiwe3
User
Beiträge: 12
Registriert: Samstag 21. August 2021, 14:46

Hallo Dennis,
ich weiss ja, dass "Eingeben" keine start() Methode hat.
Das Problem liegt bei mir, ich habe mich nicht klar ausgedrückt wegen der Fehlermeldungen.
Ich hab die richtige command-Anweisung gesucht.
Jetzt überarbeite ich mein Programm , dank den Hinweisen von __blackjack__ und meinen Folgerungen daraus.
Ich brauche in dem Fall die Klasse "Eingeben" (die auch gar keine Klasse ist) gar nicht, der "master" wird dann zu einem Objekt.
Danke für deine Antwort!
Wenn ich nach den Änderungen im Programm noch Probleme habe melde ich mich wieder.
Gruss Reiner
Antworten