Call außerhalb Gui - tkinter.TclError: invalid command name

Fragen zu Tkinter.
Antworten
Georgi87
User
Beiträge: 3
Registriert: Montag 5. April 2010, 13:52

Hallo zusammen,

ich bin noch unerfahren, was TKinter-programmierung angeht und habe trotz langer Suche keine Lösung für folgendes Problem gefunden:

Ich möchte einen Wert (z.B. Background) eines Widgets durch einen Funktionsaufruf außerhalb der Application-Klasse verändern. Folgender Code erzeugt bei mir leider den Fehler _tkinter.TclError: invalid command name ".22933952". Ich weiß nicht, wie ich weiter vorgehen soll.
Ich bin für jede Hilfe dankbar. Danke!

Code: Alles auswählen

from Tkinter import *
class Application(Frame):
	def __init__(self, master=None):
		Frame.__init__(self, master) 
		self.grid()
		self.entry = Entry()
		self.entry.grid()
		
	def setBG(self, color):
		self.entry['background'] = color
			
app = Application()
app.master.title("Sample application")
app.mainloop()

app.setBG("#FFF000")
[/code]
BlackJack

@Georgi87: Der Aufruf `app.mainloop()` kehrt erst zurück wenn die GUI geschlossen wurde. Und dann kannst Du keine Hintergrundfarbe mehr setzen, denn das Widget existiert zu dem Zeitpunkt nicht mehr.

Was willst Du denn *eigentlich* machen?

Ansonsten der übliche Hinweis das `*`-Importe "böse" sind und man die vermeiden sollte. ``import Tkinter as tk`` ist recht verbreitet.

Wenn man `grid()` ohne Argumente verwendet, könnte man auch `pack()` nehmen.

`setBG()` würde nach Style-Guide `set_bg()` heissen.
Georgi87
User
Beiträge: 3
Registriert: Montag 5. April 2010, 13:52

Danke für die schnelle Antwort und zusätzlichen Hinweise, ich werde sie beachten!

Was ich erreichen möchte:

In meinem eigentlichen Programm läuft in einem loop mein Programm und das soll Werte in der Gui manipulieren (zb Hintergrundfarbe). Das Programm ist aber nicht in der Gui klasse enthalten. -> Ich möchte von einem anderen Objekt aus eine Funktion in der GUI aufrufen.

Beispiel:

Code: Alles auswählen

# Datei1
import Tkinter as tk

class Gui(tk.Frame):
	def __init__(self, master=None):
		tk.Frame.__init__(self, master) 
		self.pack()
		self.entry = tk.Entry()
		self.entry.pack()
		
	def set_bg(self, color):
		self.entry['background'] = color
			
gui = Gui()
gui.master.title("Sample application")
gui.mainloop()

# Datei2
import time
from Datei1 import gui

class Application(object):
	def __init__(self):
		pass
	
	def start(self):
		while True:
			time.sleep(1)
			gui.set_bg("#FFF000")
			
app = Application()

app.start()
[/code]
BlackJack

@Georgi87: Das geht so nicht wirklich. GUI-Programmierung funktioniert so nicht. Die Hauptschleife wird von der GUI selbst gestellt, da kann kein eigener Code parallel laufen, der auf die GUI zugreift. Das darf man sowieso nur aus dem Thread aus tun, in dem die GUI-Hauptschleife läuft.

Also entweder Du strukturierst Dein Programm um, so dass zum Beispiel die `after()`-Methode auf Widgets anstelle von `sleep()` und einer Endlosschleife verwendet wird, oder Du musst einen separaten Thread mit dem `threading`-Modul starten und zum Beispiel über eine Queue mit dem GUI-Thread kommunizieren. Die kann man dann da auch wieder mit Hilfe der `after()`-Methode regelmässig abfragen.
Georgi87
User
Beiträge: 3
Registriert: Montag 5. April 2010, 13:52

Gut zu wissen :) Das Projekt war ursprünglich ohne Gui gedacht, daher dieser parallele Ablauf. Ich werde nun versuchen den Code in die GUI-Schleife zu integrieren. Ich melde mich, wenn es neue Probleme gibt. Vielen Dank auf jeden Fall.
Antworten