# This is meant to draw Start and Stop buttons and a label
# The Start button should start a loop in which the label
# is configured to change colour and text.
# At each pass through the loop the variable self.stop is checked:
# if True the loop should terminate.
# The Stop button should terminate the loop by setting the
# variable self.stop to True.
# I have two problems:
# 1. the Stop button does not interrupt the loop
# 2. the label only shows its reconfigured state at the end of the loop
# Please, what are my misconceptions about how this works, and what
# do I need to do to make it do what I expected?
# What I am really trying to do is show an animation but have a button
# to enable users to stop it.
# Thanks in advance for any advice.
from Tkinter import *
import time
class SGWidget(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.top_frame = Frame(bg='green')
self.top_frame.grid()
self.makeToolbar()
self.label = Label(self.top_frame,
text = 'Text',bg='orange')
self.label.grid()
def makeToolbar(self):
self.toolbar_text = ['Start','Stop']
self.toolbar_length = len(self.toolbar_text)
self.toolbar_buttons = [None] * self.toolbar_length
for toolbar_index in range(self.toolbar_length):
text = self.toolbar_text[toolbar_index]
bg = 'yellow'
button_id = Button(self.top_frame,
text=text,
background=bg)
button_id.grid(row=0, column=toolbar_index)
self.toolbar_buttons[toolbar_index] = button_id
def toolbar_button_handler(event, self=self, button=toolbar_index):
return self.service_toolbar(button)
button_id.bind("<Button-1>", toolbar_button_handler)
def service_toolbar(self, toolbar_index):
if toolbar_index == 0:
self.stop = False
print self.stop
self.blink()
if toolbar_index == 1:
self.stop = True
print self.stop
def blink(self):
for i in range(10):
print 'looping',self.stop
self.label.configure(bg = 'black',text='black')
self.label.update_idletasks()
time.sleep(1)
self.label.configure(bg = 'white',text='white')
self.label.update_idletasks()
if self.stop == True: break
if __name__ == '__main__':
SGWidget().mainloop()
sneekula 969 Nearly a Posting Maven
Your initial problems stem from the fact that you are mixing tabs and spaces in your indentations. It really loused up the code on my editor. Stick with spaces (4) only!
Also, when you click the stop button during sleep(1), it most likely will not respond. You may need to use Tkinter's after().
rodG 0 Newbie Poster
Sorry about the tabs - new version below if anyone else wants a copy. Also I've replaced the sleep by a loop to slow things down. As will be seen it makes no difference (except being machine speed dependent), so I'm doing something pretty basic wrong.
# This is meant to draw Start and Stop buttons and a label
# The Start button should start a loop in which the label
# is configured to change colour and text.
# At each pass through the loop the variable self.stop is checked:
# if True the loop should terminate.
# The Stop button should terminate the loop by setting the
# variable self.stop to True.
# I have two problems:
# 1. the Stop button does not interrupt the loop
# 2. the label only shows its reconfigured state at the end of the loop
# Please, what are my misconceptions about how this works, and what
# do I need to do to make it do what I expected?
# What I am really trying to do is show an animation but have a button
# to enable users to stop it.
from Tkinter import *
import time
class SGWidget(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.top_frame = Frame(bg='green')
self.top_frame.grid()
self.top_frame.update_idletasks()
self.makeToolbar()
self.label = Label(self.top_frame,
text = 'Text',bg='orange')
self.label.grid()
def makeToolbar(self):
self.toolbar_text = ['Start','Stop']
self.toolbar_length = len(self.toolbar_text)
self.toolbar_buttons = [None] * self.toolbar_length
for toolbar_index in range(self.toolbar_length):
text = self.toolbar_text[toolbar_index]
bg = 'yellow'
button_id = Button(self.top_frame,
text=text,
background=bg)
button_id.grid(row=0, column=toolbar_index)
self.toolbar_buttons[toolbar_index] = button_id
def toolbar_button_handler(event, self=self, button=toolbar_index):
return self.service_toolbar(button)
button_id.bind("<Button-1>", toolbar_button_handler)
def service_toolbar(self, toolbar_index):
if toolbar_index == 0:
self.stop = False
print self.stop
self.blink()
if toolbar_index == 1:
self.stop = True
print self.stop
def blink(self):
for i in range(10):
print 'looping',self.stop
self.label.configure(bg = 'black',text='black')
self.label.update_idletasks()
#time.sleep(1)
j = 0
for k in range(10000000):
j += 1
self.label.configure(bg = 'white',text='white')
self.label.update_idletasks()
if self.stop == True: break
if __name__ == '__main__':
SGWidget().mainloop()
a1eio 16 Junior Poster
You should definitely use tkinters .after() function, it enters a local event loop which means it doesn't block your program.
def blink(self):
if not self.stop: # check self.stop is false before proceeding
print 'looping',self.stop
self.label.configure(bg=choice(COLORS))
self.label.update_idletasks()
self.after(100, self.blink) # after 100 ms, call function self.blink
choice is a function imported from random,
COLORS is a list containing colors, eg: ['green','red','blue']
etc
Hope that helps
rodG 0 Newbie Poster
Thanks for the suggestion. I still cannot get it to work. Please supply a working solution embedded in my code.
a1eio 16 Junior Poster
# This is meant to draw Start and Stop buttons and a label
# The Start button should start a loop in which the label
# is configured to change colour and text.
# At each pass through the loop the variable self.stop is checked:
# if True the loop should terminate.
# The Stop button should terminate the loop by setting the
# variable self.stop to True.
# I have two problems:
# 1. the Stop button does not interrupt the loop
# 2. the label only shows its reconfigured state at the end of the loop
# Please, what are my misconceptions about how this works, and what
# do I need to do to make it do what I expected?
# What I am really trying to do is show an animation but have a button
# to enable users to stop it.
from Tkinter import *
import time
from random import choice
COLORS = ['red','green','blue','orange','brown','black','white','purple','violet']
class SGWidget(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.top_frame = Frame(bg='green')
self.top_frame.grid()
self.top_frame.update_idletasks()
self.makeToolbar()
self.label = Label(self.top_frame,
text = 'Text',bg='orange')
self.label.grid()
def makeToolbar(self):
self.toolbar_text = ['Start','Stop']
self.toolbar_length = len(self.toolbar_text)
self.toolbar_buttons = [None] * self.toolbar_length
for toolbar_index in range(self.toolbar_length):
text = self.toolbar_text[toolbar_index]
bg = 'yellow'
button_id = Button(self.top_frame,
text=text,
background=bg)
button_id.grid(row=0, column=toolbar_index)
self.toolbar_buttons[toolbar_index] = button_id
def toolbar_button_handler(event, self=self, button=toolbar_index):
return self.service_toolbar(button)
button_id.bind("<Button-1>", toolbar_button_handler)
def service_toolbar(self, toolbar_index):
if toolbar_index == 0:
self.stop = False
print self.stop
self.blink()
if toolbar_index == 1:
self.stop = True
print self.stop
def blink(self):
if not self.stop:
print 'looping',self.stop
self.label.configure(bg=choice(COLORS))
self.label.update_idletasks()
self.after(100, self.blink)
if __name__ == '__main__':
SGWidget().mainloop()
rodG 0 Newbie Poster
a1eio, Thank you so much! I clearly need to find out more about the difference between
self.after(100, self.blink)
and
self.after(100, self.blink())
Thanks again.
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.