tkinter halt or stop a function (def) from root window - python

If a function is called from the root window and the function reaches no solution or the user wants to stop the function, can this be done from the root window and if so how? The following code produces two buttons - Start starts "while" using start() but start() cannot be halted by Quit. Using root.update_idletasks() in start() produces no effect.
#!/usr/bin/env python
from Tkinter import *
def start():
while True:
print "Stop me if you can from Quit"
root.update_idletasks()
root = Tk()
root.title('Example')
button1 = Button(root,text = 'Start', command = start)
button1.grid(row = 0, column = 0)
button2 = Button(root,text = 'Quit', command = root.destroy)
button2.grid(row = 1, column = 0)
root.mainloop()

REPLACE root.update_idletasks() WITH root.update() and start() kills the root window from button2.
#!/usr/bin/env python
from Tkinter import *
def start():
while True:
print "Stop me if you can from Quit"
root.update()
root = Tk()
root.title('Example')
button1 = Button(root,text = 'Start', command = start)
button1.grid(row = 0, column = 0)
button2 = Button(root,text = 'Quit', command = root.destroy)
button2.grid(row = 1, column = 0)
root.mainloop()

Related

Python tkinter: why does he want to quit?

I would need a bit of help with my code I'm writing... and although when I start the code then comes directly such a window which asks me if I want to close it.
Does anyone have an idea where this could come from?
The code should open a window where I have some buttons to open some other windows with sliders to control DMX Lights.
Here is the code:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from print_dict import pd
from time import sleep
from tkinter import messagebox
Pultdatas = {'DMXtype':512,
'columns':2,
'rows':8,
'slider':8,
'modes':4
}
root = Tk()
root.configure(background='gray')
root.title('DMX-Pult v2')
Screens = {'mainscreen':[root,{}]}
def on_closing(screen):
if messagebox.askokcancel("Quit", f"Do you want to quit Scanner {screen}?"):
Screens[screen][0].destroy()
def setmode(screen,mode):
print(f'setmode on screen {screen} to {mode}')
for i in Screens[screen][1]['modesel']:
print(i)
i.config(bg='gray')
Screens[screen][1]['modesel'][mode].config(bg='green')
def pressed(btn):
print('pressed Button: ' + str(btn))
if not Screens.__contains__(btn):
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i+1}", bg='gray', fg='white', command=lambda name = i:setmode(btn,name)))
Screens[btn][1]['modesel'][i].grid(row=i,column=0)
setmode(btn,0)
else:
if Screens[btn][0].winfo_exists() == 1:
sleep(0.2)
print('This window exist.')
Screens[btn][0].attributes('-topmost', True)
Screens[btn][0].update()
Screens[btn][0].attributes('-topmost', False)
else:
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i + 1}", bg='gray', fg='white',
command=lambda name=i: setmode(btn, name)))
Screens[btn][1]['modesel'][i].grid(row=i, column=0)
Screens[btn][0].protocol("WM_DELETE_WINDOW", lambda name = btn:on_closing(name))
setmode(btn, 0)
print()
def close():
if messagebox.askokcancel("Quit", f"Do you want to quit?"):
for screen in Screens:
print(f'closed {Screens[screen][0].title()} Succesfully')
Screens[screen][0].destroy()
tmpint = 0
Screens['mainscreen'][1]['Back'] = Button(root, text='close all',bg='gray',fg='white',command=close)
Screens['mainscreen'][1]['Back'].grid(row=0,column=0)
for column in range(Pultdatas['columns']):
for row in range(Pultdatas['rows']):
tmpint += 1
Screens['mainscreen'][1][tmpint] = Button(root, text=f"Scanner {tmpint}", bg='gray', fg='white', command=lambda name = tmpint:pressed(name))
Screens['mainscreen'][1][tmpint].grid(row=row+1,column=column)
pd(Screens)
root.protocol("WM_DELETE_WINDOW", close())
root.mainloop()
You can just change this line of code
root.protocol("WM_DELETE_WINDOW", close())
To this:
root.protocol("WM_DELETE_WINDOW", close)
You don't need to write (), we can just write handler not as function.
For more info you can visit here

Stopping program with button Tkinter Python 3

I have a program that works with an user interface : I start it using a button and I would like to have the possibility to stop it during the process using the user interface:
The problem is : When I start the program, I cannot click on any buttons because when I drag the mouse in the tkinter window I have the "looping" / "waiting" cursor and it doesn't allow me to click on any buttons inside the interface.
I tried to start the infinit loop function in a new thread, but I don't know if it is really a good way to solve my problem... Any of you have any solutions ?
I try to simulate my problem with a simple code :
from tkinter import *
import loop
window = Tk()
window.title("test")
start = Button(window, text="start", bg ="green", command=loop.start)
stop = Button(window, text="stop", bg ="green", command=loop.stop)
thread = Button(window, text="threads", bg ="green", command=loop.how_many_threads)
start.grid(column = 1, row = 1)
stop.grid(column = 2, row = 1)
thread.grid(column = 3 , row = 1)
window.mainloop()
and few functions :
import threading
continu = True
def infinit(x):
cpt = 0
while(x):
cpt += 1
#print(cpt)
print("loop is over !")
def start():
threadSimulation = threading.Thread(target= infinit(continu)).start()
def stop():
self.continu = False
def how_many_threads():
for t in threading.enumerate():
print("thread names : ",t.getName())
Here's how to fix your implementation. The biggest error is that you have to provide arguments to the thread in the args part, not like a normal function call.
import tkinter as tk
import threading
import time
def infinit(x):
cpt = 0
while(continu):
cpt += 1
print(cpt)
time.sleep(1)
print("loop is over !")
def start():
threadSimulation = threading.Thread(target= infinit, args=(continu,))
threadSimulation.daemon = True
threadSimulation.start()
def stop():
global continu
continu = False
def how_many_threads():
for t in threading.enumerate():
print("thread names : ",t.getName())
continu = True
window = tk.Tk()
window.title("test")
start = tk.Button(window, text="start", bg ="green", command=start)
stop = tk.Button(window, text="stop", bg ="green", command=stop)
thread = tk.Button(window, text="threads", bg ="green", command=how_many_threads)
start.grid(column = 1, row = 1)
stop.grid(column = 2, row = 1)
thread.grid(column = 3 , row = 1)
window.mainloop()
If you want to close the program, you can use "window.quit" in the command section of your button like this:
stop = Button(window, text="stop", bg ="green", command=window.quit)

End multi scripts running on tkinter

I am trying to end the process of multi-scripts running on tkinter by a click of the end process created button. However, this does not seem to work when any of the scripts are running in an infinite loop to stop the process.
Here is my code:
import os
import sys
from tkinter import *
import tkinter.messagebox as tkmsg
root = Tk(className=" x") # creates root window
# all components of thw window will come here
Label(root,text='Enter Load Value or Choose a test action',font=("Helvetica", 16), width=40, height=2).pack(side=TOP)
svalue = StringVar() # defines the widget state as string
w = Entry(root,textvariable=svalue).pack(side=LEFT,padx=10) # adds a textarea widget
def act():
print ("Value entered")
print ('%s' % svalue.get())
def script_1():
os.system('python script1_1.py')
def script_2():
os.system('python script1_2.py')
global root
while 1:
root.update()
pass
def script_3():
os.system('python script1_3.py')
def script_4():
os.system('python script1_4.py')
def script_5():
os.system('python script1_5.py')
def quit():
tkmsg.showinfo("Stopped", "Stopped")
sys.exit
if __name__ == '__main__':
global root
root = Frame ()
root.pack ()
button0 = Button(root,text="Load", command=act).pack(side=LEFT,padx=10)
button1 = Button(root,text="Test 1",command=script_1).pack(side=LEFT,padx=10)
button2 = Button(root,text="Test 2",command=script_2).pack(side=LEFT,padx=10)
button3 = Button(root,text="Test 3",command=script_3).pack(side=LEFT,padx=10)
button4 = Button(root,text="Test 4",command=script_4).pack(side=LEFT,padx=10)
button5 = Button(root,text="Test 5",command=script_5).pack(side=LEFT,padx=10)
button6 = Button(root,fg="red",text="End process",command=quit).pack(side=LEFT,padx=10)
button.mainloop() # an event loop to invoke custom function "act"
root.mainloop() # To keep GUI window running

How to make a Tkinter window not resizable?

I need a Python script that uses the Tkinter module to create a static (not resizable) window.
I have a pretty simple Tkinter script but I don't want it to be resizable. How do I prevent a Tkinter window from being resizable? I honestly don't know what to do.
This is my script:
from tkinter import *
import ctypes, os
def callback():
active.set(False)
quitButton.destroy()
JustGo = Button(root, text=" Keep Going!", command= lambda: KeepGoing())
JustGo.pack()
JustGo.place(x=150, y=110)
#root.destroy() # Uncomment this to close the window
def sleep():
if not active.get(): return
root.after(1000, sleep)
timeLeft.set(timeLeft.get()-1)
timeOutLabel['text'] = "Time Left: " + str(timeLeft.get()) #Update the label
if timeLeft.get() == 0: #sleep if timeLeft = 0
os.system("Powercfg -H OFF")
os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
def KeepGoing():
active.set(True)
sleep()
quitButton1 = Button(root, text="do not sleep!", command=callback)
quitButton1.pack()
quitButton1.place(x=150, y=110)
root = Tk()
root.geometry("400x268")
root.title("Alert")
root.configure(background='light blue')
timeLeft = IntVar()
timeLeft.set(10) # Time in seconds until shutdown
active = BooleanVar()
active.set(True) # Something to show us that countdown is still going.
label = Label(root, text="ALERT this device will go to sleep soon!", fg="red")
label.config(font=("Courier", 12))
label.configure(background='light blue')
label.pack()
timeOutLabel = Label(root, text = 'Time left: ' + str(timeLeft.get()), background='light blue') # Label to show how much time we have left.
timeOutLabel.pack()
quitButton = Button(root, text="do not sleep!", command=callback)
quitButton.pack()
quitButton.place(x=150, y=110)
root.after(0, sleep)
root.mainloop()
The resizable method on the root window takes two boolean parameters to describe whether the window is resizable in the X and Y direction. To make it completely fixed in size, set both parameters to False:
root.resizable(False, False)

Interrupting Loops in a tkinter GUI via a button.

I'm coding a timer app, which has encountered a lot of difficulties, but one of the first ones has been in making a loop that can be broken by the press of a button. I've looked into it, and my research shows I should use threading, but I couldn't figure out how it would work.
What I decided to try, then, was to make an exception when I invoked a keyboard interrupt, and then make a button that calls that same interrupt. However, my current code refuses to interrupt when I ctrl-c.
My sample code looks like this
from Tkinter import *
from sys import exit
class Timer:
def __init__(self, master):
buttonstart = Button(master, text = "Start", fg = "blue", command = self.start)
buttonstart.grid(row = 1, column = 0)
buttonquit = Button(master, text = "Quit", fg = "blue", command= quit)
buttonquit.grid(row = 1, column = 2)
global timertext
timertext = DoubleVar()
timertext.set(0)
display = Label(master, textvariable = timertext)
display.grid(row = 0, column = 0)
timertext.set(timertext)
def timerlogic(self):
pass
def pause(self):
pass
def start(self):
global timertext
try:
while True:
#do things
except KeyboardInterrupt:
print "Interrupted"
def lap(self):
pass
root = Tk()
app = Timer(root)
root.mainloop()
root.destroy()
Basically, I don't think my code as it stands is viable, but I don't know how to edit it to make a loop I can interrupt as needed.
You set some variable to True or False. Also, a while loop interrupts the Tkinter loop so Tkinter will do nothing until the while loop exits. Use Tkinter's after function instead.
from Tkinter import *
##from sys import exit
class Timer:
def __init__(self, master):
self.master=master
buttonstart = Button(master, text = "Start", fg = "blue", command = self.start)
buttonstart.grid(row = 1, column = 0)
buttonquit = Button(master, text = "Quit", fg = "blue", command=self.quitit)
buttonquit.grid(row = 1, column = 2)
self.timertext = DoubleVar()
self.timertext.set(0)
display = Label(master, textvariable = self.timertext)
display.grid(row = 0, column = 0)
## timertext.set(timertext) ## Huh!!
self.timeit=False
def increment_timer(self):
ctr=int(self.timertext.get())
self.timertext.set(ctr+1)
if self.timeit:
self.master.after(500, self.increment_timer)
def start(self):
self.timeit=True
self.increment_timer()
def quitit(self):
self.timeit=False
root = Tk()
app = Timer(root)
root.mainloop()

Categories

Resources