Seite 1 von 1
Problem beim beenden einer Funktion
Verfasst: Montag 12. Mai 2014, 14:44
von DrW3sk3r
Halli Hallo,
ich habe ein Problem dazu müsst ihr erst das Script lesen.
Code: Alles auswählen
#!/usr/bin/env python
#coding: utf-8
from Tkinter import *
root = Tk()
def start():
for i in range(0,1000):
print(i)
def stop():
return start
startbtn = Button(root, text="Start", command=start)
startbtn.pack()
stopbtn = Button(root, text="Stop", command=stop)
stopbtn.pack()
root.mainloop()
Mein Problem ist wenn ich den Startbutton drücke fängt er an zu Zählen. Aber wenn ich Stop drücke passiert nicht und er Zählt weiter.
Ich wollte wissen wie kann ich die Funktion Start mit dem Stopbutton beenden?
Ich freue mich auf jede Antwort
Re: Problem beim beenden einer Funktion
Verfasst: Montag 12. Mai 2014, 15:27
von BlackJack
@DrW3sk3r: So funktionieren GUIs nicht. Die Funktion wird von der GUI-Hauptschleife aufgerufen, die dafür zuständig ist, dass auf Schaltflächen reagiert wird und die GUI aktualisiert wird. Solange die Funktion also läuft, kann logischerweise die Hauptschleife nicht laufen. Die geht erst weiter wenn die Funktion am Ende angekommen ist und die Kontrolle wieder dorthin abgibt.
Eine Möglichkeit regelmässig etwas zu tun, zum Beispiel eine Zahl hochzuzählen und auszugeben ist die `after()`-Methode auf Widgets. Damit kann man eine Funktion oder Methode angeben die nach einer angegebenen Zeit von der GUI-Hauptschleife aufgerufen wird. Die kann dann *einen* Schritt machen, und sich zum Beispiel selber wieder für einen Aufruf für den nächsten Schritt vormerken lassen. Da man sich hier Zustände über mehrere Aufrufe hinweg merken muss (läuft der Zähler gerade, welche Zahl ist aktuell), ist eine idiomatische Lösung eine mit einer Klasse die das kapselt. Für GUI-Programmierung sollte man IMHO *vorher* schon halbwegs sicher in der objektorientierten Programmierung sein.
Re: Problem beim beenden einer Funktion
Verfasst: Montag 12. Mai 2014, 15:33
von DrW3sk3r
Das heist also ich kann diese dann nicht stoppen und muss warten bis diese durch ist damit die Haufunktion wieder laufen kann.
Korrigiere mich wenn ich falsch liege
Aber ist möglich oder?
Re: Problem beim beenden einer Funktion
Verfasst: Montag 12. Mai 2014, 15:42
von BlackJack
@DrW3sk3r: Wenn eine Funktion läuft kann sie sich nur selber stoppen, denn wenn sie läuft, dann läuft ja *der* Code und kein anderer. (Threading lasse ich hier mal aussen vor, weil das wenn man es nicht wirklich braucht unnötige Probleme mit sich bringt. Insbesondere mit GUIs.)
Was für eine „Haufunktion”? Und *was* ist jetzt möglich (oder nicht)?
Edit:
Code: Alles auswählen
#!/usr/bin/env python
from __future__ import print_function
import Tkinter as tk
class Application(object):
def __init__(self, parent):
self.parent = parent
self.number_iterator = None
self.start_button = tk.Button(parent, text='Start', command=self.start)
self.start_button.pack()
self.stop_button = tk.Button(
parent, text='Stop', state=tk.DISABLED, command=self.stop
)
self.stop_button.pack()
def _count(self):
try:
if self.number_iterator:
print(next(self.number_iterator))
except StopIteration:
self.stop()
else:
self.parent.after_idle(self._count)
def start(self):
assert self.number_iterator is None
self.start_button['state'] = tk.DISABLED
self.stop_button['state'] = tk.NORMAL
self.number_iterator = iter(range(10000))
self.parent.after_idle(self._count)
def stop(self):
self.start_button['state'] = tk.NORMAL
self.stop_button['state'] = tk.DISABLED
self.number_iterator = None
def main():
root = tk.Tk()
_application = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Re: Problem beim beenden einer Funktion
Verfasst: Montag 12. Mai 2014, 18:29
von wuf
Hi DrW3sk3r
Hier noch eine weitere Variante mit 'after()' in einer Klasse:
Code: Alles auswählen
#!/usr/bin/env python
#coding: utf-8
from functools import partial
try:
#~~ For Python 2.x
import Tkinter as tk
except ImportError:
#~~ For Python 3.x
import tkinter as tk
TIME_INTERVAL = 100 # 100ms
MAX_COUNT = 10000
FONT_READOUT = ("Helvetica", 20, "bold")
BG_READOUT = 'khaki1'
FG_READOUT = 'blue'
class MyCounter(tk.Frame):
def __init__(self, parent_widget, interval=TIME_INTERVAL,
max_count=MAX_COUNT, **options):
self.interval = interval
self.max_count = max_count
self.counter = 0
self.run = False
tk.Frame.__init__(self, parent_widget, **options)
self.build_counter_readout()
self.build_command_buttons()
self.cycler()
def build_command_buttons(self):
button_frame = tk.Frame(self, bg=BG_READOUT)
button_frame.pack(fill='x', ipadx=2, ipady=2)
button_names = ["Start", "Stop", "Reset"]
for button_name in button_names:
button = tk.Button(button_frame, text=button_name)
button.pack(side='left', expand=True)
button.bind('<Button-1>', partial(
self.command_button_callback, button_name))
def build_counter_readout(self):
self.readout_var = tk.IntVar()
tk.Label(self, textvariable=self.readout_var, font=FONT_READOUT,
bg=BG_READOUT, fg=FG_READOUT, width=12).pack(fill='x')
def command_button_callback(self, button_name, args):
if button_name == "Start" and not self.run:
self.run = True
if button_name == "Stop":
self.run = False
if button_name == "Reset":
self.counter = 0
self.readout_var.set(self.counter)
def cycler(self):
if self.run and self.counter < self.max_count:
self.counter += 1
self.readout_var.set(self.counter)
self.after(self.interval, self.cycler)
def main():
root = tk.Tk()
MyCounter(root, 1, relief='raised', bd=1).pack(padx=2, pady=(2, 0))
MyCounter(root, relief='raised', bd=1).pack(padx=2, pady=(2, 0))
MyCounter(root, 500, 100, relief='raised', bd=1).pack(padx=2, pady=(2, 0))
root.mainloop()
if __name__ == '__main__':
main()
Gruss wuf
