Seite 1 von 1
Fehler mit entry.get und set.labeltext
Verfasst: Montag 12. Dezember 2011, 17:54
von daz18
Ich bin noch Python Anfänger und wollte eigentlich ein Stein_Schere_Papier Programm programmieren. Dafür möchte ich ein Eingabefeld erstellen, doch leider kann ich weder den text noch den Titel setzen und zudem sagt er mir, dass es einen Fehler mit der get methode gibt. Ich hoffe ihr könnt mir weiterhelfen.
Code: Alles auswählen
from Tkinter import *
class Eingabefeld():
def __init__(self):
self.Fenster = Tk()
self.titel = "Test"
self.Fenster.title(self.titel)
self.frame = Frame(self.Fenster)
self.frame.pack()
self.text = Label(self.frame)
self.text.grid(row = 0,column = 0)
self.text2 = Label(self.frame)
self.text2.grid(row = 1,column = 0)
self.entry = Entry(self.frame)
self.entry.grid(row=0, column=1)
self.entry2 = Entry(self.frame)
self.entry2.grid(row=1, column=1)
self.okb = Button(self.frame,text='Ok',padx=100)
self.okb.grid(row=2)
self.Fenster.mainloop()
self.nameget = self.entry.get()
def titel(self,x):
self.titel=x
def text1(self,x):
self.text.config(text = x)
def text2(self,x):
self.text2.config(text = x)
root = Eingabefeld()
root.titel('Hello World')
root.text1('Geben sie ihren Vornamen ein')
root.text2('Geben sie ihren Namen ein')
Fehlermeldung beim schließen des Programms:
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\user\Downloads\probe4.py", line 34, in <module>
root = Eingabefeld()
File "C:\Users\user\Downloads\probe4.py", line 23, in __init__
self.nameget = self.entry.get()
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2391, in get
return self.tk.call(self._w, 'get')
TclError: invalid command name ".45501640L.45501768L"
Re: Fehler mit entry.get und set.labeltext
Verfasst: Montag 12. Dezember 2011, 20:05
von wuf
Hi daz18
Kannst du das folgende Skript einmal ausprobieren:
Code: Alles auswählen
import Tkinter as tk
class Eingabefeld():
def __init__(self, callback):
self.callback = callback
self.frame = tk.Frame(app)
self.frame.pack()
self.text1 = tk.Label(self.frame, anchor='w')
self.text1.grid(row=0, column=0, padx=5, sticky='we')
self.text2 = tk.Label(self.frame, anchor='w')
self.text2.grid(row=1, column=0, padx=5, sticky='we')
self.entry1 = tk.Entry(self.frame, bg='white')
self.entry1.grid(row=0, column=1)
self.entry2 = tk.Entry(self.frame, bg='white')
self.entry2.grid(row=1, column=1)
self.ok_button = tk.Button(self.frame,text='Ok', command=self.entry_ok)
self.ok_button.grid(row=2, column=0, sticky='we')
def entry_ok(self):
self.callback(self.entry1, self.entry2)
def set_text1(self, text):
self.text1.config(text=text)
def set_text2(self, text):
self.text2.config(text=text)
def callback(entry_1, entry_2):
print 'Eingabe-1:', entry_1.get()
print 'Eingabe-2:', entry_2.get()
app = tk.Tk()
app.title('Hello World')
input_field = Eingabefeld(callback)
input_field.set_text1('Geben sie ihren Vornamen ein:')
input_field.set_text2('Geben sie ihren Namen ein:')
input_field.entry1.focus_set()
app.mainloop()
Gruß wuf

Re: Fehler mit entry.get und set.labeltext
Verfasst: Montag 12. Dezember 2011, 21:23
von daz18
Vielen Dank für die Antwort, der Code hilft mir weiter.
Ich verstehe nur nicht wieso die entry.get Methode nicht bei mir geklappt hat und wieso import Tkinter as tk besser ist.
Gruß David
Re: Fehler mit entry.get und set.labeltext
Verfasst: Montag 12. Dezember 2011, 21:48
von BlackJack
@daz18: Mit dem Sternchenimport holst Du Dir ≈200 Namen in das Modul, mit wuf's Alternative nur einen.
Schau Dir mal die Zeile vor Deinem Fehler an. Die Hauptschleife kehrt erst zurück wenn sie zum Beispiel durch das schliessen des Fensters beendet wurde. Dann ist das Fenster aber weg, und damit auch das `entry`-Widget.
Re: Fehler mit entry.get und set.labeltext
Verfasst: Montag 12. Dezember 2011, 22:03
von wuf
@daz18:
Gehe ich richtig in der Annahme, dass du die Entry-Widgets mit dem aktivieren der OK-Schaltfläche auslesen möchtest oder nur beim schliessen des Hauptfensters?
Gruß wuf

Re: Fehler mit entry.get und set.labeltext
Verfasst: Dienstag 13. Dezember 2011, 12:37
von daz18
Also eigentlich möchte ich die eingegeben Daten in einer Variable speichern und danach durch drücken des OK-Buttons das Fenster schließen.
Re: Fehler mit entry.get und set.labeltext
Verfasst: Dienstag 13. Dezember 2011, 23:59
von problembär
Hi,
1. Man sollte nicht ".grid()" und ".pack()" vermischen. Entscheide Dich bitte für ein Konzept. Die meisten ziehen wohl ".pack()" vor. Das wäre auch meine Empfehlung. Im Beispiel unten habe ich das noch so gelassen, wie Du es geschrieben hattest.
2. Normalerweise bleibt das Hauptfenster geöffnet, solange das Programm läuft. Wenn Du das Hauptfenster schließt, mußt Du Dich entscheiden, wo Du die Werte weiterverarbeiten willst. Ich habe dazu unten mal eine Klasse "MainClass" dazugefügt. Bei großen Programmen ist es hilfreich, GUI und Datenverarbeitung sogar ganz zu trennen. Dazu verwendet man meist nicht nur zwei, sondern drei Klassen, siehe hier unter
MVC.
Beachte: Das GUI und die GUI-Klasse sind zwei verschiedene Dinge: Wenn das Hauptfenster mit ".destroy()" geschlossen wird, kehrt der Programmablauf zu der __init__-Funktion in "MainClass" zurück. Die GUI-Klasse "Eingabefeld" ist dort aber über die Instanz ".eingfeld" immer noch bekannt.
Hier also ein Codevorschlag:
Code: Alles auswählen
#!/usr/bin/python
# coding: iso-8859-1
import Tkinter as tk
class MainClass:
def __init__(self):
self.eingfeld = Eingabefeld(titel = 'Hello World',
text1 = 'Geben sie ihren Vornamen ein',
text2 = 'Geben sie ihren Namen ein')
for i in self.eingfeld.values.keys():
print "Feldname: " + i
print "Wert: " + self.eingfeld.values[i]
print
class Eingabefeld:
def __init__(self, titel, text1, text2):
self.values = {}
self.Fenster = tk.Tk()
self.titel = titel
self.Fenster.title(self.titel)
self.frame = tk.Frame(self.Fenster)
self.frame.pack()
self.text = tk.Label(self.frame, text = text1)
self.text.grid(row = 0,column = 0)
self.text2 = tk.Label(self.frame, text = text2)
self.text2.grid(row = 1,column = 0)
self.entry = tk.Entry(self.frame, fg = 'black', bg = 'white')
self.entry.grid(row=0, column=1)
self.entry.focus()
self.entry2 = tk.Entry(self.frame, fg = 'black', bg = 'white')
self.entry2.grid(row=1, column=1)
self.okb = tk.Button(self.frame, text='Ok', command = self.getValue)
self.okb.grid(row=2)
self.Fenster.mainloop()
def getValue(self):
self.values = {"entry1" : self.entry.get(),
"entry2" : self.entry2.get()}
self.Fenster.destroy()
if __name__ == "__main__":
MainClass()
Re: Fehler mit entry.get und set.labeltext
Verfasst: Donnerstag 15. Dezember 2011, 14:58
von daz18
Vielen Dank für den Code, den übernehm ich aufjedenfall.
Re: Fehler mit entry.get und set.labeltext
Verfasst: Freitag 16. Dezember 2011, 17:59
von problembär
daz18 hat geschrieben:Vielen Dank für den Code, den übernehm ich aufjedenfall.
Das ist nett, aber eigentlich ist das nur ein kleines Beispiel. Das ist noch nicht so gut, daß man es so verwenden sollte. Es sollte Dir eigentlich nur ein bißchen dabei helfen, das Ganze zu verstehen, damit Du es dann selbst nochmal neu und besser schreibst.

Re: Fehler mit entry.get und set.labeltext
Verfasst: Sonntag 18. Dezember 2011, 18:30
von daz18
Ok ich habe nun ein weiteres Problem bei meinem Stein Schere Papier Programm.
Es geht darum das ich den Befehl des Buttons nachträglich hinzufügen will.
Das Problem ist das er den Befehl einmal ausführt, wenn man das Programm startet und dann nicht mehr.
Hier der Code:
Code: Alles auswählen
import Tkinter as tk
import random
class Spiel_ssp:
# Konstruktor
def __init__(self):
# Attribute: nick
self.nick = 'Spieler1'
self.nick2 = 'Spieler2'
self.punkte = 0
self.cpunkte = 0
self.cnick = 'Computer'
#Fuer Spieler1
def set_nick(self,wert):
self.nick = wert
def get_nick(self):
return self.nick
#Fuer Spieler2
def set_nick2(self,wert):
self.nick2 = wert
def get_nick2(self):
return self.nick2
def auswertung_mittel(self,x):
if x == 1:
print(self.nick +' spielt Stein')
if x == 2:
print(self.nick +' spielt Schere')
if x == 3:
print(self.nick +' spielt Papier')
y = random.randint(1,3)
if y == 1:
print(self.cnick +' spielt Stein')
if y == 2:
print(self.cnick +' spielt Schere')
if y == 3:
print(self.cnick +' spielt Papier')
if x == y:
print ('Unentschieden')
print(self.punkte, self.cpunkte)
elif x == 2 and y == 3:
print (self.nick + ' gewinnt')
self.punkte = self.punkte + 1
print(self.punkte, self.cpunkte)
elif x == 3 and y == 1:
print (self.nick + ' gewinnt')
self.punkte = self.punkte + 1
print(self.punkte, self.cpunkte)
elif x == 1 and y == 2:
print (self.nick + ' gewinnt')
self.punkte = self.punkte + 1
print (self.punkte, self.cpunkte)
else :
print (self.cnick + ' gewinnt')
self.cpunkte += 1
print(self.punkte, self.cpunkte)
class Buttonfeld():
def __init__(self,Fenster,text1,text2,text3):
self.frame = tk.Frame(Fenster)
self.frame.pack()
self.b1 = tk.Button(self.frame,text = text1)
self.b1.pack()
self.b2 = tk.Button(self.frame,text = text2)
self.b2.pack()
self.b3 = tk.Button(self.frame,text = text3)
self.b3.pack()
def set_config(self,x):
self.b1['command'] = lambda:x
def set_config2(self,x):
self.b2['command'] = lambda:x
def set_config3(self,x):
self.b3['command'] = lambda:x
class MainClass:
def __init__(self):
self.app = tk.Tk()
self.app2 = Spiel_ssp()
self.bfeld = Buttonfeld(self.app,
text1 = 'Stein',
text2 = 'Schere',
text3 = 'Papier')
self.bfeld.set_config(self.app2.auswertung_mittel(1))
self.bfeld.set_config2(self.app2.auswertung_mittel(2))
self.bfeld.set_config3(self.app2.auswertung_mittel(3))
self.app.mainloop()
MainClass()
Re: Fehler mit entry.get und set.labeltext
Verfasst: Sonntag 18. Dezember 2011, 20:11
von nomnom
Hier sind mal ein paar Dinge, die du beachten solltest:
- Deine Klasse `MainClass` ist sinnlos: Du instanziierst die Klasse sowieso auf Modulebene. Besser ist es, wenn du das in eine Funktion packst und dann die Funktion in einem if-Block aufrufst:
- Da du Python 2 verwendest, sollten deine Klassen von `object` erben, und du kannst auch `print` ohne Klammern verwenden, da du bei deinem Programm durch `print()` keine Vorzüge hast.
- Deine `get_…`- bzw `set_…`-Methoden sind auch sinnlos: Du kannst auch einfach auf app.nick zugreifen, und es verändern.
- Du solltest deskriptive Namen für deine Objekte wählen. Schau dir auch mal PEP 8 an.
- `x = x + 1` geht in Python auch kürzer: `x += 1`
- Magische Zahlen wie 1/2/3 sollten auch vermieden werden, und durch Namen repräsentiert werden: STEIN/SCHERE/PAPIER
"lambda: x" ist sinnfrei, das liefert nur x zurück. Und x ist in deinem Programm immer `None`, und jetzt überleg, warum!

Re: Fehler mit entry.get und set.labeltext
Verfasst: Sonntag 18. Dezember 2011, 20:15
von wuf
Hi daz18
Kannst du das folgende einmal ausprobieren:
Code: Alles auswählen
import Tkinter as tk
import random
class Spiel_ssp:
# Konstruktor
def __init__(self):
# Attribute: nick
self.nick = 'Spieler1'
self.nick2 = 'Spieler2'
self.punkte = 0
self.cpunkte = 0
self.cnick = 'Computer'
#Fuer Spieler1
def set_nick(self,wert):
self.nick = wert
def get_nick(self):
return self.nick
#Fuer Spieler2
def set_nick2(self,wert):
self.nick2 = wert
def get_nick2(self):
return self.nick2
def auswertung_mittel(self,x):
if x == 1:
print(self.nick +' spielt Stein')
if x == 2:
print(self.nick +' spielt Schere')
if x == 3:
print(self.nick +' spielt Papier')
y = random.randint(1,3)
if y == 1:
print(self.cnick +' spielt Stein')
if y == 2:
print(self.cnick +' spielt Schere')
if y == 3:
print(self.cnick +' spielt Papier')
if x == y:
print ('Unentschieden')
print(self.punkte, self.cpunkte)
elif x == 2 and y == 3:
print (self.nick + ' gewinnt')
self.punkte = self.punkte + 1
print(self.punkte, self.cpunkte)
elif x == 3 and y == 1:
print (self.nick + ' gewinnt')
self.punkte = self.punkte + 1
print(self.punkte, self.cpunkte)
elif x == 1 and y == 2:
print (self.nick + ' gewinnt')
self.punkte = self.punkte + 1
print (self.punkte, self.cpunkte)
else :
print (self.cnick + ' gewinnt')
self.cpunkte += 1
print(self.punkte, self.cpunkte)
class Buttonfeld():
def __init__(self,Fenster,text1,text2,text3):
self.frame = tk.Frame(Fenster)
self.frame.pack()
self.b1 = tk.Button(self.frame,text = text1)
self.b1.pack()
self.b2 = tk.Button(self.frame,text = text2)
self.b2.pack()
self.b3 = tk.Button(self.frame,text = text3)
self.b3.pack()
def set_config(self, call_back, x):
self.b1['command'] = lambda: call_back(x)
def set_config2(self, call_back, x):
self.b2['command'] = lambda: call_back(x)
def set_config3(self, call_back, x):
self.b3['command'] = lambda: call_back(x)
class MainClass:
def __init__(self):
self.app = tk.Tk()
self.app2 = Spiel_ssp()
self.bfeld = Buttonfeld(self.app,
text1 = 'Stein',
text2 = 'Schere',
text3 = 'Papier')
self.bfeld.set_config(self.app2.auswertung_mittel,1)
self.bfeld.set_config2(self.app2.auswertung_mittel,2)
self.bfeld.set_config3(self.app2.auswertung_mittel,3)
self.app.mainloop()
MainClass()
Gruß wuf

Re: Fehler mit entry.get und set.labeltext
Verfasst: Sonntag 18. Dezember 2011, 20:41
von daz18
Vielen Dank Wuf, dass du mein Problem gelöst hast.
@nomnom
Danke für die Tipps, aber ich verstehe ehrlich gesagt nicht, wieso x immer none ist.
Re: Fehler mit entry.get und set.labeltext
Verfasst: Sonntag 18. Dezember 2011, 21:21
von nomnom
daz18 hat geschrieben:Danke für die Tipps, aber ich verstehe ehrlich gesagt nicht, wieso x immer none ist.
Deswegen solltest du ja drüber nachdenken.

Es ist wirklich nicht schwer. Wenn du das nicht verstehst, dann solltest du nochmal das
Tutorial durcharbeiten.
Re: Fehler mit entry.get und set.labeltext
Verfasst: Montag 19. Dezember 2011, 15:19
von problembär
@daz18: Könnte sein, daß Dir noch nicht ganz klar ist, wie das Programm bei einer GUI-Anwendung abläuft. Das ist ja anders als bei einer Konsolenanwendung, bei der lediglich ein Befehl nach dem anderen abgearbeitet wird.
Also: Bei einer GUI-Anwendung (in diesem Fall mit Tkinter) definierst Du zuerst die Fensterelemente und rufst dann ".mainloop()" des "tk.Tk"-Objekts auf. Dann hängt die Anwendung sozusagen im Mainloop. Von dort werden Funktionen aufgerufen, die z.B. bei der Button-Definition über "command = ..." angegeben wurden.
Nach Ablauf der jeweiligen Funktion kehrt die Anwendung wieder in den Mainloop zurück. Das geht solange, bis die ".destroy()"-Methode des "tk.Tk"-Objekts aufgerufen wird, und also das Hauptfenster geschlossen wird.
Das mit dem Mainloop ist nötig, weil die Fensteroberfläche mehrere Benutzereingaben ("Events") von mehreren Widgets gleichzeitig verarbeiten können muß.
Hier wieder ein kleines Beispiel zum Verständnis:
Code: Alles auswählen
#!/usr/bin/python
# coding: iso-8859-1
import Tkinter as tk
class TkApp(object):
def __init__(self):
self.clicked = 0
self.app = tk.Tk()
self.app.title("Testfenster")
self.btn = tk.Button(text = "Knopf", command = self.btnClick)
self.btn.pack(padx = 60, pady = 30)
self.exit_btn = tk.Button(text = "Exit", command = self.app.destroy)
self.exit_btn.pack(padx = 60, pady = 20)
self.app.mainloop()
def btnClick(self):
self.clicked += 1
print "Knopf wurde " + str(self.clicked) + " mal gedrückt."
TkApp()
Ist es jetzt etwas klarer?