Eingabefeld entsperren

Fragen zu Tkinter.
GHoeberth
User
Beiträge: 6
Registriert: Mittwoch 27. August 2014, 17:44

Eingabefeld entsperren

Beitragvon GHoeberth » Donnerstag 30. März 2017, 15:38

Hallo ...
Ich versuche gerade irgendwiein Tkinter einzusteigen... :(
Wie kann ich auf Elemente des Fensters aus dem Programm zugreifen?
Ein Beipiel:
  1. from tkinter import *
  2.  
  3. def init(top, gui):
  4.     global w, top_level, root
  5.     w = gui
  6.     top_level = top
  7.     root = top
  8.  
  9. def destroy_window():
  10.     global top_level
  11.     top_level.destroy()
  12.     top_level = None
  13.  
  14. def vp_start_gui():
  15.     global val, w, root
  16.     root = Tk()
  17.     top = New_Toplevel_1 (root)
  18.     init(root, top)
  19.     root.mainloop()
  20.  
  21. def destroy_New_Toplevel_1():
  22.     global w
  23.     w.destroy()
  24.     w = None
  25.  
  26. class New_Toplevel_1:
  27.     def __init__(self, top=None):
  28.         top.title("New Toplevel 1")
  29.  
  30.         self.Entry1 = Entry(top)
  31.         self.Entry1.place(relx=0.1, rely=0.17, relheight=0.17, relwidth=0.8)
  32.         self.Entry1.configure(state=DISABLED)
  33.  
  34.         self.Button1 = Button(top)
  35.         self.Button1.place(relx=0.25, rely=0.5, height=24, width=67)
  36.         self.Button1.configure(command=Entsp)
  37.         self.Button1.configure(text='''Entsperren''')
  38.  
  39. def Entsp():
  40.     print("Entsperren")
  41.     """
  42.    Was muss ich hier einfügen, damit das Textfeld (Entry1)
  43.    von state=DISABELD auf state=NORMAL gesetzt wird?
  44.    """
  45.  
  46. if __name__ == '__main__':
  47.     vp_start_gui()


Gibt es irgendwo eine Referenz für Tkinter, bei der man grundsätzlich nachsehen kann, wie man die Eigenschaften der GUI-Elemente abfragt und wie man sie verändert?
Wäre für einen Link dankbar. Google hat mir bisher nicht weitergeholfen. :(

herzlichen Gruß
Gerhard
Zuletzt geändert von BlackJack am Donnerstag 30. März 2017, 15:45, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
BlackJack
Moderator
Beiträge: 33023
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Eingabefeld entsperren

Beitragvon BlackJack » Donnerstag 30. März 2017, 16:00

@GHoeberth: Als erstes solltest Du mal ``global`` vergessen. Das schafft mehr Probleme als es löst und spätestens für GUI-Programmierung muss man sich mit objektorientierter Programmierung beschäftigen und dann gibt's auch keinerlei Rechtfertigung für ``global`` mehr.

Wie man `state` auf `DISABLED` setzt weisst Du doch schon. Auf `NORMAL` setzen funktioniert genauso. Wobei `configure()` im Programm bisher unnötig eingesetzt wird: man kann die Optionen auch gleich beim erstellen des jeweiligen Widgets als Schlüsselwortargumente angeben. Und selbst wenn man `configure()` verwendet und zwei Optionen setzen möchte, sollte man das in *einem* Aufruf machen und nicht zwei. Wenn ich nur eine Option ändern möchte, nehme ich eher die „subscription“-Syntax, also ``widget['option'] = value``.

Referenzen sind in der Python-Dokumentation zum `tkinter`-Modul verlinkt. Die von Effbot und die von New Mexico Tech sind am brauchbarsten, IMHO.

Von `place()` würde ich auch mit relativen Angaben Abstand nehmen.

Kryptische Abkürzungen (`vp_*`? `Entsp`) und nummerierte Namen sind keine gute Idee.
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
GHoeberth
User
Beiträge: 6
Registriert: Mittwoch 27. August 2014, 17:44

Re: Eingabefeld entsperren

Beitragvon GHoeberth » Donnerstag 30. März 2017, 17:22

Hallo BlackJack,

also erstmal danke für die schnelle Reaktion.
Allerdings kann ich soviel noch nicht damit anfangen.
Die Datei, die ich als CODE eingefügt habe ist ein von mir auf reine Funktionalität gekürzte Version von PAGE, daher die "kryptischen Abkürzungen".
"Global" stand bei den Variablen deshalb dabei, weil PAGE das GUI in zwei Dateien ausgibt (die ich zu einer zusammengefasst habe).

Ich mach mich jetzt mal über "subscription" schlau ;-)

Danke
Gerhard
Benutzeravatar
BlackJack
Moderator
Beiträge: 33023
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Eingabefeld entsperren

Beitragvon BlackJack » Donnerstag 30. März 2017, 17:59

@GHoeberth: Das dieser Code von einem Werkzeug generiert wurde wäre eine nützliche Information gewesen. So musste man ja davon ausgehen Du hast den selbst geschrieben und wüsstest was die Sachen bedeuten weil Du sie ja geschrieben hättest.

Ich würde von dem Programm dringend abraten. Die Funktionen mit den ganzen ``global``\s und insgesamt die Struktur die das Programm ausspuckt sind extrem gruselig.
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
GHoeberth
User
Beiträge: 6
Registriert: Mittwoch 27. August 2014, 17:44

Re: Eingabefeld entsperren

Beitragvon GHoeberth » Freitag 31. März 2017, 05:39

Okay,

also als ersten Schritt einmal einen anderen GUI-Builder...
Benutzeravatar
BlackJack
Moderator
Beiträge: 33023
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Eingabefeld entsperren

Beitragvon BlackJack » Freitag 31. März 2017, 10:04

@GHoeberth: Bei Tk würde ich eher sagen gar keinen GUI-Builder.

Edit: Würde ich für den Anfang auch bei jedem anderen GUI-Rahmenwerk sagen, damit man die Komponenten und Zusammenhänge kennenlernt.
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
Alfons Mittelmeyer
User
Beiträge: 1622
Registriert: Freitag 31. Juli 2015, 13:34

Re: Eingabefeld entsperren

Beitragvon Alfons Mittelmeyer » Donnerstag 20. April 2017, 23:26

BlackJack hat geschrieben:@GHoeberth: Als erstes solltest Du mal ``global`` vergessen. Das schafft mehr Probleme als es löst und spätestens für GUI-Programmierung muss man sich mit objektorientierter Programmierung beschäftigen und dann gibt's auch keinerlei Rechtfertigung für ``global`` mehr.


Also, in diesem Forum, ist man der Ansicht, alles soll Objektorientiert sein und global ist total verpönt. Aber global kann man durch Objektorientierung - das heißt Klassen, leicht ersetzen:

  1. class MyData():
  2.     def __init__(self):
  3.         self.var1 = "Test 1"
  4.         self.var2 = "Test 2"
  5.  
  6. my_OOP_global = MyData()
  7.  
  8. class andere_Klasse():
  9.     def __init__(self):
  10.  
  11.         print(my_OOP_global.var1)
  12.         print(my_OOP_global.var2)
  13.  
  14.         my_OOP_global.var1 = "Test 3"
  15.  
  16.         print(my_OOP_global.var1)
  17.         print(my_OOP_global.var2)
  18.  
  19. andere_Klasse()


Statt global geht also genausogut auch OOP
Benutzeravatar
__deets__
User
Beiträge: 751
Registriert: Mittwoch 14. Oktober 2015, 14:29

Re: Eingabefeld entsperren

Beitragvon __deets__ » Freitag 21. April 2017, 00:05

Globaler Zustand ist nicht nur "in diesem Forum", sondern ganz allgemein verpönt. Weil er lose Kopplung, Wiederverwendbarkeit und eine lokale Betrachtung verhindert.

Und das durch Einführung eines mutablen Objektes Modul-globalen Zustand erzeugt hast beweist jetzt was genau? Ein dict hätte genauso gereicht, und mir fallen da auf Anhieb noch diverse andere "Tricks" ein, macht aber alles keinen Unterschied. Denn nur weil man das global Statement gespart hat, ist es IMMER noch globaler Zustand. Semantik und so. Weiß ich ja, biste auf dem Kriegsfuß mit. Aber glaubst du das ist jetzt irgendwie clever, oder belegt irgendeinen Punkt?
Alfons Mittelmeyer
User
Beiträge: 1622
Registriert: Freitag 31. Juli 2015, 13:34

Re: Eingabefeld entsperren

Beitragvon Alfons Mittelmeyer » Freitag 21. April 2017, 06:38

@__deets__: lass Dich von Benennungen nicht in das Boxhorn jagen.

Soll man tkinter benutzen oder nicht?

ist tkinter nach "import tkinter as my_OOP_global" nun global?
soll man es also nicht benutzen?

Worum es geht ist doch: nicht eine einzige Klasse machen, in welche man alles hineistopft, sondern sinnvoll in Zusammengehöriges unterteilen. Dabei kann es aber auch sein, dass ein Modul Sinnvoll Zusamengehöriges enthält, welches man nicht weiter in verschiedene Klassen unterteilen will.

'gobal' soll man nicht nehmen, sondern eine oder mehrere Klassen sind gut. Denn man kann dann solche Variablen auch auslagern, etwa "import mydata as my_OOP_global". Solches Auslagern braucht man, wenn mehrere Module darauf zugreifen sollen.
Zuletzt geändert von Alfons Mittelmeyer am Freitag 21. April 2017, 06:51, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 6116
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Eingabefeld entsperren

Beitragvon Sirius3 » Freitag 21. April 2017, 06:50

@Alfons Mittelmeyer: Deine unqualifizierten Bemerkungen beweisen, dass Du keine Ahnung hast, was ein globaler Zustand ist, den es zu vermeiden gilt. tkinter ist ein Modul und damit global Verfügbar, es ist aber keine Variable, die man von überall her ändern kann/sollte.
Alfons Mittelmeyer
User
Beiträge: 1622
Registriert: Freitag 31. Juli 2015, 13:34

Re: Eingabefeld entsperren

Beitragvon Alfons Mittelmeyer » Freitag 21. April 2017, 19:25

@__deets__. stimmt, habe ich nicht ganz richtig gemacht, aber so ist es nun richtig, oder?

  1. class MyData():
  2.     def __init__(self):
  3.         self.var1 = "Test 1"
  4.         self.var2 = "Test 2"
  5.  
  6.     def set_var1(self,value):
  7.         self.var1 = value
  8.  
  9.     def set_var2(self,value):
  10.         self.var2 = value
  11.  
  12.     def get_var1(self):
  13.         return self.var1
  14.  
  15.     def get_var2(self):
  16.         return self.var2
  17.  
  18.  
  19. my_OOP_global = MyData()
  20.  
  21. class andere_Klasse():
  22.     def __init__(self):
  23.  
  24.         print(my_OOP_global.get_var1())
  25.         print(my_OOP_global.get_var2())
  26.  
  27.         my_OOP_global.set_var1("Test 3")
  28.  
  29.         print(my_OOP_global.get_var1())
  30.         print(my_OOP_global.get_var2())
  31.  
  32. andere_Klasse()
Zuletzt geändert von Alfons Mittelmeyer am Freitag 21. April 2017, 19:33, insgesamt 1-mal geändert.
Benutzeravatar
BlackJack
Moderator
Beiträge: 33023
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: Eingabefeld entsperren

Beitragvon BlackJack » Freitag 21. April 2017, 19:31

@Alfons Mittelmeyer: Nein natürlich nicht, und das weisst Du auch. Könntest Du das getrolle bitte einstellen. :roll:
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
Alfons Mittelmeyer
User
Beiträge: 1622
Registriert: Freitag 31. Juli 2015, 13:34

Re: Eingabefeld entsperren

Beitragvon Alfons Mittelmeyer » Freitag 21. April 2017, 20:04

BlackJack hat geschrieben:@Alfons Mittelmeyer: Nein natürlich nicht, und das weisst Du auch. Könntest Du das getrolle bitte einstellen. :roll:


Ich trolle doch nicht, ich will nur von Euch wissen, wie es stimmt und warum. Stimmt es vielleicht so?

  1. class MyData():
  2.     def __init__(self):
  3.         self.var1 = "Test 1"
  4.         self.var2 = "Test 2"
  5.  
  6. class andere_Klasse(MyData):
  7.     def __init__(self):
  8.  
  9.         MyData.__init__(self)
  10.  
  11.         print(self.var1)
  12.         print(self.var2)
  13.  
  14.         self.var1 = "Test 3"
  15.  
  16.         print(self.var1)
  17.         print(self.var2)
  18.  
  19. andere_Klasse()
Alfons Mittelmeyer
User
Beiträge: 1622
Registriert: Freitag 31. Juli 2015, 13:34

Re: Eingabefeld entsperren

Beitragvon Alfons Mittelmeyer » Samstag 22. April 2017, 12:57

GHoeberth hat geschrieben:Hallo ...
Ich versuche gerade irgendwiein Tkinter einzusteigen... :(
Wie kann ich auf Elemente des Fensters aus dem Programm zugreifen?


indem Du zuerst einmal den überflüssigen Mist aufräumst.

def init?

Eine sinnlose Verwirrfunktion, die außerdem falsch ist, sie bekommt in vp_start_gui folgende Parameter übergeben: root, top

root ist klar
top ist aber kein Toplevel GUI Element sondern überhaupt kein GUI Element - ein sinnloses Objekt, das in __init__ lediglich Gui Elemente erstellte, sozusagen ist das nur eine Funktion gewesen.

top ist also etwas, mit dem man gar nichts anfangen kann.

Die Funktion init beginnt mit verwirrenden Parametern. Jetzt heißt die übergebene root plötzlich top und das übergebene sinnlose top wird zu gui. Das sinnlose top wird dann in eine globalen Variablen w gespeichert.

Danach wird eine globale Variable top_level belegt mit:

top_level = root
Und dann noch völlig überflüssig:
root = root

destroy_New_Toplevel_1?

destroy_New_Toplevel_1() kann nicht funktionieren, weil es kein tkinter GUI Objekt ist, sondern etwas Sinnloses bei dem kein destroy() geht.

destroy_window?

destroy_window: soll das Anwendungsfenster schließen, was dann das Programm beenden würde. Was soll aber diese Funktion, wenn kein Button dafür da ist? Einfach mit der Maus rechts oben im Fenster geklickt, schließt auch das Programm, also eine unnötige Funktion.

Und dann sollte der Rest klar geordnet und als Klasse implementiert werden:

Sinnvollerweise enthält eine Klasse die Definition eines Container Widgets (hier das Anwendungsfensters) nebst Erzeugen und Platzieren der Gui Elemente darin und die Rückruffunktionen am Besten als Methoden, weil sie dann schon selber das self des Containerwidgets bekommen, mit dem man dann die Wiggets im Containerwidget ansprechen kann.

  1. import tkinter as tk
  2.  
  3. class Application(tk.Tk):
  4.     def __init__(self):
  5.         tk.Tk.__init__(self)
  6.  
  7.         self.title("New Toplevel 1")
  8.  
  9.         self.Entry1 = tk.Entry(self,state=tk.DISABLED)
  10.         self.Entry1.place(relx=0.1, rely=0.17, relheight=0.17, relwidth=0.8 )
  11.  
  12.         self.Button1 = tk.Button(self,text='Entsperren',command=self.entsperren)
  13.         self.Button1.place(relx=0.25, rely=0.5)
  14.  
  15.     def entsperren(self):
  16.         print("Entsperren")
  17.         self.Entry1['state']=tk.NORMAL
  18.  
  19. if __name__ == '__main__':
  20.     Application().mainloop()


Man braucht also hier keine globale Variable, es genügt: self

Das kann bei einer komplexen GUI auch anders sein. Etwa ein Blinkschalter wird an einem Ort gefertigt, eine Blinkleuchte an einem anderen Ort. Man kann dann nicht gleich imblementieren, dass dieser Blinkschalter die nämliche Blinkleuchte ansteuern soll, man kann nur die Ausgabe eines Blinksignals implementieren. Beim späteren Zusammenbau muss man dann den Schalter mit der Leuchte verkabeln, mit Hilfe eines dafür vorgesehenen Kabels in einem Kabelstrang. Man muss also doch unter Umständen zentrale Schaltstellen bzw. Schaltverbindungen haben.

Noch Fragen?
Benutzeravatar
wuf
User
Beiträge: 1310
Registriert: Sonntag 8. Juni 2003, 09:50

Re: Eingabefeld entsperren

Beitragvon wuf » Samstag 22. April 2017, 23:58

Hi GHoeberth

Hier noch eine andere Variante:
  1. # -*- coding: utf-8 -*-
  2.  
  3. try:
  4.     # Tkinter for Python 2.xx
  5.     import Tkinter as tk
  6. except ImportError:
  7.     # Tkinter for Python 3.xx
  8.     import tkinter as tk
  9.    
  10. APP_WIN_XPOS = 100
  11. APP_WIN_YPOS = 100
  12.  
  13.  
  14. class Application(tk.Frame):
  15.     def __init__(self,app_win):
  16.         self.app_win = app_win
  17.        
  18.         app_win.protocol("WM_DELETE_WINDOW", self.close)
  19.        
  20.         tk.Frame.__init__(self, app_win)
  21.        
  22.         self.entry = tk.Entry(self, state=tk.DISABLED)
  23.         self.entry.pack(padx=10, pady=10)
  24.  
  25.         self.button = tk.Button(self, text='Entsperren',
  26.             command=self.entsperren)
  27.         self.button.pack(padx=10, pady=10)
  28.        
  29.     def entsperren(self):
  30.         self.entry.config(state=tk.NORMAL)
  31.         self.entry.focus_set()
  32.  
  33.     def close(self):
  34.         print("Mach noch etwas for dem schliessen der Anwendung")
  35.         self.app_win.destroy()
  36.        
  37. def main():
  38.     app_win=tk.Tk()
  39.     app_win.title("New Toplevel 1")
  40.     app_win.geometry("+{}+{}".format(APP_WIN_XPOS, APP_WIN_YPOS))
  41.     Application(app_win).pack(expand=True)
  42.     app_win.mainloop()
  43.    
  44. if __name__ == '__main__':
  45.     main()

Gruss wuf :wink:
Take it easy Mates!

Wer ist online?

Mitglieder in diesem Forum: Mephisto