in Echtzeit aktualisieren

Fragen zu Tkinter.
Antworten
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Donnerstag 25. Dezember 2008, 23:57

Hallo!


Ich kenne mich nicht wirklich mit Tkinter aus und habe deshalb zwei (grundlegende) Fragen.

die erste:
Ich habe ein recht kompliziertes Programm. Um dieses grafisch auszugeben, habe ich eine Tkinter-Definition geschrieben. zum Beispiel so:

Code: Alles auswählen

def ausgabe(x,y):

    fenster=Tk()
    fenster.title('Fenster')
    rahmen=Frame(fenster,background='grey')
    rahmen.pack()
    Label1=Label(rahmen,width=3,background='grey',text=x)
    Label2.grid(row=1,column=1)
    Label2=Label(rahmen,width=3,background='grey',text=y)
    Label2.grid(row=1,column=2)
etc.

Das Problem ist jetzt nur, dass sich im weiteren Programmverlauf die in der Ausgabe-Definition aufgerufenen Variabeln verändern. Das sollen sie aber auch dann wirklich grafisch tun. Sobald sich x und y verändern, soll sich auch der Text der Labels verändern.
Wie kriege ich es also hin, den Text der Labels in Echtzeit ändern zu lassen? Ein erneutes aufrufen der Definition kreiert jedesmal ein neues Fenster, aber es soll ja im alten geändert werden.

die zweite Frage:
Ich habe auch noch verschiedene Buttons eingebaut; diese haben eine Aufschrift und eine bestimmte Farbe. Ich möchte nun, dass wenn man auf zwei Buttons hintereinander klickt, sie ihre Position vertauschen.
Ich kann dies mit meinen Mittlen tun, wenn ich für jeden Button eine eigene Definition schreibe, die ich dann mit 'command=VERTAUSCHENX' aufrufe.

Code: Alles auswählen

beispiel1=Button(rahmen,background=farbe,command=VERTAUSCHEN1)
Da ich aber recht viele Buttons habe, ist das sehr mühsam. Es gibt bestimmt eine bessere Lösung, oder nicht?

:D


Für Hilfe bin ich dankbar!
Gruß
Paul
busfahrer
User
Beiträge: 111
Registriert: Donnerstag 9. Oktober 2008, 17:42

Freitag 26. Dezember 2008, 11:47

Hallo

ich denke bezüglich deines Labels solltest du dir
das hier mal ansehen http://infohost.nmt.edu/tcc/help/pubs/t ... ables.html


Gruß...busfahrer
Alles wird gut ;-)
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Freitag 26. Dezember 2008, 14:18

Hallo Peak_me !

Code: Alles auswählen

import Tkinter as tk

class My_Gui(object):
    
    def __init__(self, root):
        self.buttons = ["Button 1", "Button 2", "Button 3"]
        self.button_control = list()
        self.change_button = list()
        for column, text in enumerate(self.buttons):
            button = tk.Button(root, text=text, command=lambda 
                index=column: self.change_text(index))
            button.grid(row=0, column=column)
            self.button_control.append(button)
            
    def change_text(self, index):
        self.change_button.append(index)
        if len(self.change_button) == 2:
            text_change = list()
            for index in self.change_button:
                text_change.append(self.buttons[index])
            text_change.reverse()
            for index, text in zip(self.change_button, text_change):
                self.buttons[index] = text
                self.button_control[index].config(text=text)
            self.change_button = list()
            
def main():
    root = tk.Tk()
    My_Gui(root)
    root.title("My Program")
    root.mainloop()
if __name__ == "__main__":
    main()
gruss frank
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Samstag 27. Dezember 2008, 00:00

Der Link hat mir sehr weitergeholfen! danke; ich glaube, dass ich das mit dem Aktualisieren jetzt hinbekomme.
Wenn jetzt noch jemand eine Idee fuer das Vertauschen der Buttons haette, waere ich noch gluecklicher :P
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Samstag 27. Dezember 2008, 00:27

Kaytec hat doch schon eine Lösung für das Vertauschen
der Buttons gebracht.

Aber vielleicht kann dieses ja auch noch zu Deinem Glücke
beitragen:

Code: Alles auswählen

#!/usr/bin/env python

####

import Tkinter as tk

####

class Exchanger(object):

   
  def __init__(self, n):

    colors = ['#%02x0000' % (i * 255 // n) for i in xrange(n)]   
    self.root = tk.Tk()
    self.root.title('Exchanger')
    
    self.contents = [('%s' % i, col) for i, col in enumerate(colors)]
    self.svars = [tk.StringVar() for i in self.contents]         
    self.buttons = [tk.Button(self.root, textvariable=v, width=4,
                              command=lambda i=i: self.exchange(i))
                    for i, v in enumerate(self.svars)]
    self.labels = [tk.Label(self.root, textvariable=v, fg='white', width=2,
                            relief=tk.SUNKEN)
                   for v in self.svars]
    
    self.conf_buttons()
    for i, (but, lab) in enumerate(zip(self.buttons, self.labels)):
      but.grid(row=i, column=0)
      lab.grid(row=i, column=1)

    self.state = []


  def exchange(self, i):

    self.state += [i]
    if len(self.state) == 2:
      i0, i1 = self.state
      self.contents[i0], self.contents[i1] = self.contents[i1], \
                                             self.contents[i0]
      self.state = []
      
    self.conf_buttons()
    

  def conf_buttons(self):
  
    for var, cont, but, lab in zip(self.svars, self.contents,
                                   self.buttons, self.labels):
      text, col = cont
      var.set(text)
      but.config(fg=col)
      lab.config(bg=col)


  def run(self):

    self.root.mainloop()

####

if __name__ == '__main__':

  Exchanger(10).run() 
:wink:
yipyip
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Dienstag 30. Dezember 2008, 20:16

achso, das war fuer das Aktualisieren... Ich habe mir es kurz angeschaut und es nichts verstanden. Und da keine Erklaerung da war, habe ich es ignoriert...
Aber ich habe das mit dem vertauschen eigentlich hinbekommen, waere da nicht dieses Problem:

Mein Programm ist sehr lang, deswegen habe ich einen Test-Ausschnitt erstellt, der das Problem erhält:

Code: Alles auswählen

from Tkinter import *

fenster=Tk()
fenster.title('test')
rahmen=Frame(fenster,height=500,width=100,background='purple')
rahmen.pack()

reihenfolge=[]

def ver1(reihenfolge):
    reihenfolge.append(1)
    print reihenfolge

def ver2(reihenfolge):
    reihenfolge.append(2)
    print reihenfolge

def ausgabe():
    schalter1=Button(rahmen,width=3,height=4,command=ver1)
    schalter1.grid(row=1,column=1)

    schalter2=Button(rahmen,width=3,height=4,command=ver2)
    schalter2.grid(row=1,column=2)

ausgabe()
Die Fehlermeldung ist
"Exception in Tkinter callback
Traceback (most recent call last):
File "G:\Python\lib\lib-tk\Tkinter.py", line 1403, in __call__
return self.func(*args)
TypeError: ver1() takes exactly 1 argument (0 given)".
Das soll mir wahrscheinlich sagen, dass ich bei "command=ver1" die Übergabe der Variable vergessen habe (ver1(reihenfolge)).
Bei dem 'command' in Buttons kann man aber nicht die Variabeln übergeben, sondern kann einfach nur die Definition nennen. Normalerweise funktioniert es so auch, aber hier nicht.


Ich habe die beiden Definitionen dann ohne Variabelnübergabe probiert:

Code: Alles auswählen

def ver1():
    reihenfolge.append(1)
    print reihenfolge

def ver2():
    reihenfolge.append(2)
    print reihenfolge
So funktioniert es dann auch, denn "reihenfolge" ist in diesem Programm eine globale Variable. Dies habe ich herausbekommen, indem ich

Code: Alles auswählen

reihenfolge=[]
am Anfang weggelassen habe.
Dann kommt 'NameError: global name 'reihenfolge' is not defined'.

In meine eigentlichen Programm kommt aber dann die Fehlermeldung:
"UnboundLocalError: local variable 'ver' referenced before assignment"

Also entweder bekomme ich das Programm ganz oben zum Laufen oder ich kann die Variable in meinem eigentlichen Programm von lokal auf global ändern. Dies ist der einzige Unterschied der beiden Programme. Ich weiß aber nicht wieso. Ich rufe beide an der exakt gleichen Stelle auf, die Struktur ist genau die gleiche. Es existieren bloß andere Definitionen drum herum, die aber überhaupt nichts mit dieser Variable zu tun haben.


danke schonmal!,
Gruß
Paul
Benutzeravatar
kaytec
User
Beiträge: 544
Registriert: Dienstag 13. Februar 2007, 21:57

Dienstag 30. Dezember 2008, 22:09

Hallo Peak_me !

Doch mit "lambda" geht es - schau mal in mein Beispiel.

gruss frank
Benutzeravatar
wuf
User
Beiträge: 1475
Registriert: Sonntag 8. Juni 2003, 09:50

Mittwoch 31. Dezember 2008, 00:27

Hallo Peak_me

Es geht um die Anweisung 'lambda' wie 'kaytec' erwähnte und schon in seinem Beispiel eingesetzt hatte.

Kannst du das folgende einmal ausprobieren:

Code: Alles auswählen

#from Tkinter import *
import Tkinter as tk

fenster = tk.Tk()
fenster.title('test')
rahmen = tk.Frame(fenster, height=500, width=100, background='purple')
rahmen.pack()

reihenfolge=[]

def ver1(reihenfolge):
    reihenfolge.append(1)
    print reihenfolge

def ver2(reihenfolge):
    reihenfolge.append(2)
    print reihenfolge

def ausgabe(param):
#    schalter1=Button(rahmen,width=3,height=4,command=ver1)
    schalter1 = tk.Button(rahmen, width=3, height=4, command=lambda
                reihenfolge=param: ver1(reihenfolge))
    schalter1.grid(row=1, column=1)

#    schalter2=Button(rahmen,width=3,height=4,command=ver2)
    schalter2 = tk.Button(rahmen, width=3, height=4, command=lambda
                reihenfolge=param: ver2(reihenfolge))

    schalter2.grid(row=1, column=2)

#ausgabe()
ausgabe(reihenfolge)

fenster.mainloop()
Der Option 'command' kann keine Referenz für den Aufruf einer 'Funktion' bzw. 'Methode' mit Argumenten zugewiesen werden:

Code: Alles auswählen

command=ver1
Mit Hilfe der 'lambda'-Anweisung ist dies aber möglich:

Code: Alles auswählen

command=lambda reihenfolge=param: ver1(reihenfolge)
Gruss wuf :wink:
Take it easy Mates!
Antworten