Restart customtkinter using button - python

this might be a noob question but I have a simple script to monitor the current in my area which I use customtkinter as my GUI.
The script have two buttons which are Start and Restart. The Start button is to start the program and the Restart in to simply to Restart the whole code again which you could see on the snippet of the code below.
import sys
import os
#from tkinter import Tk, Label, Button
import customtkinter
def restart_program():
"""Restarts the current program."""
root.destroy()
os.startfile("testbed.py")
root = customtkinter.CTk()
#Label(root, text="Hello World!").pack()
#Button(root, text="Restart", command=restart_program).pack()
label = customtkinter.CTkLabel(root, text="Hello World!").pack()
button = customtkinter.CTkButton(root, text="Restart", command=restart_program).pack()
root.mainloop()
but when I clicked on the restart button it does not execute the os.startfile("testbed.py") part is there something wrong with my logic?

Related

How to trigger again a callback function before the first call for that function has ended

Good morning,
What I am aiming for:
I want to create a button that when clicked triggers a call back function (even if that function is still running).
Module:
I am using tkinter
Problem:
When I trigger the button, the function runs, but then I cannot push the button again before the function has finished its run. I want to be able to push the button while the function is still running and have the function stop and run again from start.
My attempts:
I tried both a procedural and a OOP approach: both present the same problem
My attempt n1: Procedural approach
import time
import tkinter as tk # Import tkinter
from tkinter import ttk # Import ttk
def func():
for i in range (100):
print(i)
time.sleep(5)
win = tk.Tk() # Create instance of the Tk class
aButton = ttk.Button(win, text="Click Me!", command=func)
aButton.grid(column=0, row=0) # Adding a Button
win.mainloop() # Start GUI
My attempt n2: OOP approach
import time
import tkinter as tk # Import tkinter
from tkinter import ttk # Import ttk
class OOP():
def func(self):
for i in range (100):
print(i)
time.sleep(5)
def __init__(self):
win = tk.Tk() # Create instance of the Tk class
aButton = ttk.Button(win, text="Click Me!", command=self.func)
aButton.grid(column=0, row=0) # Adding a Button
win.mainloop() # Start GUI
oop = OOP()
Thanks
In tkinter, as with most GUI frameworks, there is a for loop running somewhere that constantly checks for user input. You are hijacking that loop to do your func processing. Tkinter can not check for user input, nor e.g. change the appearance of the button icon, because there is only one thread and you are using it.
What you will want to do is fire up a thread or process to do the work. There are lots of libraries to do parallel processing in elaborate ways if you have lots of background tasks but this will do for a single function (see also this answer).
import time
import tkinter as tk # Import tkinter
from tkinter import ttk # Import ttk
import threading
def button():
thread = threading.Thread(target=func, args=args)
thread.start()
def func():
for i in range (100):
print(i)
time.sleep(5)
win = tk.Tk() # Create instance of the Tk class
aButton = ttk.Button(win, text="Click Me!", command=button)
aButton.grid(column=0, row=0) # Adding a Button
win.mainloop() # Start GUI
If the process is long running, you might need to find a way to clean up the threads when they're done.

Having a problem with tkinter button in python

I'm using tkinter to create a window with a button, the button's command is to destroy the window and create a similar new one on click, but the moment you run the program it automatically executes the button command which leads to a spam of windows creation and destruction
from tkinter import *
import random
import tkinter as tk
j=0
def func(j):
f=Tk()
f.title("game")
f.geometry("400x350")
f["bg"]="black"
#message
Label(f,bg="black",fg="white",height=2,width=20,text=" ").pack()
Label(f,bg="black",fg="white",height=3,width=20,text="click continue to proceed\n to main menu",font=("Arial",13)).pack()
#frame
global d
d=Frame(f,bg="white",bd=1)
d.pack(fill="both",expand=True,side="bottom")
print(d.__format__)
#cancel button
def canccel():
f.destroy()
c=Canvas(d,bg="white")
b1=Button(c,bg="white",text="cancel",command=canccel)
b1.pack()
c.pack(padx=90, pady=22,side=tk.LEFT)
#play button
if j==0:
k=Canvas(d,bg="white")
b2=Button(k,bg="red",text="continue!",command= [print("hehe"),func(-1)])
b2.pack()
k.pack(padx=15,pady=0,side=LEFT)
else:
j=random.randrange(0,400)
i=random.randrange(0,300)
k=Canvas(d,bg="white")
b2=Button(k,bg="white",text="continue!",command= [print("hehe"),func(j)])
b2.pack()
k.pack(padx=i,pady=j,side=LEFT)
f.mainloop()
func(j)

Command execution on closing "X" Tkinter MessageBox

I am trying to restart my main GUI/Halt the program flow when I Click on the "X" button in my tkinter messagebox . Any idea how can I do this ?
PS: I have read the many threads about closing the main GUI itself but nothing specific to messagebox
By default , my code proceeds to ask me for an output path using the filedailog.askdirectory() method when clicking "ok", or on closing the messagebox
My message box and the main GUI in the background
There's no simple way to add a custom handler to the "X" button. I think it's better to use messagebox.askokcancel() variation of messageboxes instead of showinfo, and halt the program if the returned result is False:
import tkinter as tk
from tkinter import messagebox, filedialog
root = tk.Tk()
def show_messagebox():
result = messagebox.askokcancel("Output path", "Please select an output file path")
if result:
filedialog.askdirectory()
else:
messagebox.showinfo("Program is halted")
tk.Button(root, text="Show messagebox", command=show_messagebox).pack()
root.mainloop()
Or, even simpler, you can just show filedialog.askdirectory() directly. If the user doesn't want to choose directory, they can click on the "Cancel" button, and then the program checks if there was empty value returned, and halts if so:
import tkinter as tk
from tkinter import messagebox, filedialog
root = tk.Tk()
def show_askdirectory():
directory = filedialog.askdirectory(title="Please select an output file path")
if not directory:
messagebox.showinfo(message="The program is halted")
else:
messagebox.showinfo(message="Chosen directory: " + directory)
tk.Button(root, text="Choose directory", command=show_askdirectory).pack()
root.mainloop()

destroy a tkinter window an proceed further

I created a tkinter Toplevel window for my application and later in the program destroyed it but after destroying the window the program doesnt get executed further and get struck there itself doing nothing . Here is the code that I used :-
#login.py
from tkinter import *
class gui:
def __init__(self):
#does something
def login(self):
self.winLogin.destroy()
def guilogin(self):
self.winLogin = Toplevel()
btn = Button(self.winLogin,command=self.login,text='asd')
btn.pack()
self.winLogin.mainloop()
#main.py
import login
from tkinter import *
main = Tk()
a = login.gui()
a.guilogin()
if True:
#some code and this part doesnot get executed
main.mainloop()
else:
main.destroy()
I run main.py file and the code get struck and do nothing before the if part . I tottaly have no idea whats wrong . Pls. Help!
As furas said in the comments, you should not call mainloop on the toplevel, instead use grab_set to disable the main window and wait_window to wait for the toplevel to be closed:
from tkinter import Tk, Toplevel, Button
def login():
top = Toplevel(root)
Button(top, text="Quit", command=top.destroy).pack()
top.grab_set() # deactivate the main GUI while top is opened
root.wait_window(top) # wait for top to be closed before doing the rest
print("logged in")
root = Tk()
Button(root, text="login", command=login).pack()
root.mainloop()

Problems using Tkinter askopenfile

I want to launch an "Open File" dialog in Tkinter in Python 2.7.
My code starts with:
from Tkinter import Frame, Tk, BOTH, Text, Menu, END
import tkFileDialog as tkfd
import fileinput
root = Tk()
global strTab
strTab = ""
def openTab(event):
r = tkfd.askopenfilename()
strTab = unicodedata.normalize('NFKD', r).encode('ascii','ignore')
Later in the code I have:
btnLoadTab = Button(root,
text="Load Tab",
width=30,height=5,
bg="white",fg="black")
btnLoadTab.bind("<Button-1>", openTab)
btnLoadTab.pack()
root.mainloop()
When I press the button an "Open File" dialog is shown, but when I select a file it closes and the button remains "clicked".
If I later call to strTab outside of openTab, it remains equal to "".
You can find workable example here: http://www.python-course.eu/tkinter_dialogs.php

Categories