For Schleife scheint nicht bei Progressbar zu funktionieren

Fragen zu Tkinter.
Antworten
mexxwell
User
Beiträge: 6
Registriert: Sonntag 24. Februar 2013, 14:55

Hallo zusammen,

ich moechte den Progressbar mittels einer for Schleife und der.step Anweisung langsame auffuellen, so dass es aussieht als wuerde er langsam aufgefuellt.
Das Problem ist, dass der Code den Durchlauf macht, aber den Progressbar nicht stueckweise erhoeht, sondern wenn er mit dem Durchlauf fertig ist, das Ergebnis im Progressbar darstellt. Es gibt also keine "Bewegung" beim auffuellen.

Was mache ich falsch?

Hier ist mein Code:

Code: Alles auswählen

import Tkinter as tk
import ttk
from Tkinter import * 
import Image as PIL
import ImageTk
import time

def click():
	for i in range(1,100):	
		pbar.step(0.1)
		time.sleep(0.5)	

def click2():
	pbar.step(-0.1)

def click3():
	pbar2.step(0.1)

def click4():
	pbar2.step(-0.1)

main= Tk();
main.title('Main')

##########################################################
# Definition der oberen Umgebungstemperatur Widgets      

Label(main,text='Umgebungstemperatur').grid(row=1,column=1)
Umg_temp_text = Label(main,text='12')
Umg_temp_text.grid(row=1,column=2)

image = PIL.open('wr1.png')
photo = ImageTk.PhotoImage(image)
Label(main,image=photo).grid(row=2,column=0)

pbar = ttk.Progressbar(main, length=300)
pbar.grid(row=2,column=1)

image2 = PIL.open('wr2.png')
photo2 = ImageTk.PhotoImage(image2)
Label(main,image=photo2).grid(row=2,column=2)

Umg_temp_scale = Label(main,text="-25  -10   0   5   10   15   20   25   30   35   40").grid(row=3,column=1)

##########################################################
# Definiton des Abstandbalkens 

canvas=Canvas(main, width=200, height=10).grid(row=4,column=1)

##########################################################
# Definition der unteren Innenraumtemperatur Widgets    

Label(main,text='Innenraumtemperatur').grid(row=5,column=1)
Inn_temp_text = Label(main,text='12')
Inn_temp_text.grid(row=5,column=2)

image3 = PIL.open('wr1.png')
photo3 = ImageTk.PhotoImage(image3)
Label(main,image=photo3).grid(row=6,column=0)

pbar2 = ttk.Progressbar(main, length=300)
pbar2.grid(row=6,column=1)

image4 = PIL.open('wr2.png')
photo4 = ImageTk.PhotoImage(image4)
Label(main,image=photo4).grid(row=6,column=2)

Inn_temp_scale = Label(main,text="-25  -10   0   5   10   15   20   25   30   35   40").grid(row=7,column=1)

#############################################################
# Testbuttons zum auffuellen und loeschen der Tmeperaturbalken sowie zyum aendern des TempLabels

Umg_temp_vor = ttk.Button(text="oben +", command=click).grid(row=8,column=0)
Umg_temp_zurueck = ttk.Button(text="oben -", command=click2).grid(row=8,column=1)
Inn_temp_vor = ttk.Button(text="unten +", command=click3).grid(row=8,column=2)
Inn_temp_zurueck = ttk.Button(text="unten -", command=click4).grid(row=8,column=3)

main.mainloop()

LG aus Wien
Zuletzt geändert von Anonymous am Sonntag 24. Februar 2013, 16:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@mexxwell: Solange Dein Code läuft, also in diesem Fall die Schleife, kann die Hauptschleife von Tkinter nicht laufen, die Deinen Code aufgerufen hat. Erst wenn der fertig ist und die Kontrolle wieder an seinen Aufrufer zurück gibt, also die Tk-Hauptschleife, wird die GUI-Anzeige aktualisiert.

GUI-Programmierung funktioniert ereignisbasiert, das heisst Du sagst auf welche Ereingnisse Du mit welcher Funktion oder Methode reagieren möchtest und gibst die Kontrolle dann an die Hauptschleife des GUI-Toolkits ab. Die ruft bei den Ereignissen die Funktionen oder Methoden auf, die Du dafür vorher angegeben hast. Und dieser Code darf dann nur relativ kurz auf das Ereignis reagieren. Wenn der Code länger läuft, dann wird die GUI dadurch blockiert.

Das was Du machen möchtest wird üblicherweise mit der `after()`-Methode auf Widgets gelöst, was sozusagen das Warten per `time.sleep()` ersetzt. Man gibt dort eine Verzögerung an und eine Funktion/Methode, die nach dieser Zeit von Tk aufgerufen werden soll. Die Funktion erledigt dann *einen* Schritt von dem was Du in der Schleife formulierst, und ruft gegebenenfalls die `after()`-Methode für sich selbst auf, um den beim nächsten Aufruf den nächsten Schritt der jetzigen Schleife auszuführen. Dazu muss man sich über die Aufrufe hinweg den aktuellen Zustand merken. Bei so einer simplen Sache wie hier geht das noch in dem man zum Beispiel einen Iterator für die Liste mit den Zahlen (`iter()`) als zusätzliches Argument bei `after()` übergibt, aber wenn es auch nur etwas komplizierter wird, kommt man nicht um objektorientierte Programmierung (OOP) herum. Dazu (und ein paar anderen Sachen) hatte ich im anderen Thema von Dir ja schon etwas geschrieben.

Statt `range()` solltest Du übrigens `xrange()` verwenden, wenn Du nicht tatsächlich eine Liste mit den Zahlen benötigst.
mexxwell
User
Beiträge: 6
Registriert: Sonntag 24. Februar 2013, 14:55

Hallo, danke erstmal fuer die schnelle und ausfuehrliche Antwort.
Die Loesung des Problems war dann dank dir eine recht einfache.
Hab den Code beigefuegt.

Vielen Dank, LG aus Wien

def click():
for i in range(1,100):
pbar.step(0.5)
for a in range(1,300):

main.update()
BlackJack

@mexxwell: Das ist keine Lösung. Das mag jetzt kurzfristig den gewünschten Effekt erzielen, aber auf Dauer wirst Du so nicht weiterkommen. Ausserdem hängt die Geschwindigkeit davon sehr von Faktoren wie Rechnergeschwindigkeit, Fenstermanager, und Grafikkarten/Treiber-Leistung ab.

Und benutze doch bitte selber mal die code-Tags für Python-Quelltext hier im Forum, damit die Einrückung sichtbar wird. Die ist wichtig in Python.
Antworten