right now am trying to make a customtkinter GUI for my code the problem that am running in which I cannot really find an answer to it is as follows, I am trying to make a button run a specific bit of code and I want to be able to do it multiple times, normally that's not a problem but in this case the code takes a bit of time to finish (1hr)
during this 1hr the GUI is not responsive till the code has been executed
so i tried to run it by threading just as follows
btn = customtkinter.CTkButton(misc_frame, text="Press",command =threading.Thread(target=main).start)
this fixes the problem of the GUI/ application freezing but it produces 2 new problems
1-once I hit the button 1 time I cannot hit it again to run the same bit of code as it is a thread
2-if I close the GUI am trying to have it so the code just terminates and I have no idea how to implement that
btn = customtkinter.CTkButton(misc_frame, text="Press",command =threading.Thread(target=main).start)
so i ran this code it solved 1 problem but brought about 2 other problems which are
1- I cannot hit the same button again to run the same function after it finished it the first time
2- if I close the GUI the code keeps on running and I would like that to happen
import tkinter
import customtkinter
import multiprocessing as mp
import os
import threading
import time
def main(button_loc):
customtkinter.CTkButton.configure(button_loc,state="disabled",fg_color="red",text= "Running" , font=('Helvetica', 18, 'bold'))
x = 0
while x <=10 :
x += 1
print("hello")
time.sleep(1)
customtkinter.CTkButton.configure(button_loc,state="normal",fg_color="green",text= "START" , font=('Helvetica', 18, 'bold'))
print("done")
#run app
if __name__ == "__main__":
# System Setting
customtkinter.set_appearance_mode("Dark")
customtkinter.set_default_color_theme("blue")
# App Frame
app = customtkinter.CTk()
app.geometry("1100x580")
app.title("Program 2.0")
#frames
Prices_frame = customtkinter.CTkFrame(app, width=500, height=260)
Prices_frame.place(x = 10, y = 10)
misc_frame = customtkinter.CTkFrame(app, width=200, height=260)
misc_frame.place(x = 520, y= 10)
#prices frame Labels
label_Runes = customtkinter.CTkLabel(Prices_frame, text="Runes", width = 10, height = 10, font=('Helvetica', 18, 'bold'))
label_Runes.place(x = 20, y=10)
label_Souls = customtkinter.CTkLabel(Prices_frame, text="Souls", width = 10, height = 10, font=('Helvetica', 18, 'bold'))
label_Souls.place(x = 140, y=10)
label_Relics = customtkinter.CTkLabel(Prices_frame, text="Relics", width = 10, height = 10, font=('Helvetica', 18, 'bold'))
label_Relics.place(x = 260, y=10)
label_Shards = customtkinter.CTkLabel(Prices_frame, text="Shards", width = 10, height = 10, font=('Helvetica', 18, 'bold'))
label_Shards.place(x = 380, y=10)
#misc_frame Labels
tax_rate = customtkinter.CTkLabel(misc_frame, text="TAX Rate:", width = 10, height = 10, font=('Helvetica', 12, 'bold'))
tax_rate.place(x = 10, y = 18 )
profit_margin = customtkinter.CTkLabel(misc_frame, text="Profit Margin:", width = 10, height = 10, font=('Helvetica', 12, 'bold'))
profit_margin.place(x = 10, y = 57 )
#prices frame Entries
entry_t4_runes = customtkinter.CTkEntry(Prices_frame, placeholder_text="T4 runes",width=100)
entry_t4_runes.place(x = 20 , y = 55)
entry_t4_souls = customtkinter.CTkEntry(Prices_frame, placeholder_text="T4 souls",width=100)
entry_t4_souls.place(x = 140 , y = 55)
entry_t4_relics = customtkinter.CTkEntry(Prices_frame, placeholder_text="T4 relics",width=100)
entry_t4_relics.place(x = 260 , y = 55)
entry_t4_shards = customtkinter.CTkEntry(Prices_frame, placeholder_text="T4 shards",width=100)
entry_t4_shards.place(x = 380 , y = 55)
entry_t5_runes = customtkinter.CTkEntry(Prices_frame, placeholder_text="T5 runes",width=100)
entry_t5_runes.place(x = 20 , y = 95)
entry_t5_souls = customtkinter.CTkEntry(Prices_frame, placeholder_text="T5 souls",width=100)
entry_t5_souls.place(x = 140 , y = 95)
entry_t5_relics = customtkinter.CTkEntry(Prices_frame, placeholder_text="T5 relics",width=100)
entry_t5_relics.place(x = 260 , y = 95)
entry_t5_shards = customtkinter.CTkEntry(Prices_frame, placeholder_text="T5 shards",width=100)
entry_t5_shards.place(x = 380 , y = 95)
entry_t6_runes = customtkinter.CTkEntry(Prices_frame, placeholder_text="T6 runes",width=100)
entry_t6_runes.place(x = 20 , y = 135)
entry_t6_souls = customtkinter.CTkEntry(Prices_frame, placeholder_text="T6 souls",width=100)
entry_t6_souls.place(x = 140 , y = 135)
entry_t6_relics = customtkinter.CTkEntry(Prices_frame, placeholder_text="T6 relics",width=100)
entry_t6_relics.place(x = 260 , y = 135)
entry_t6_shards = customtkinter.CTkEntry(Prices_frame, placeholder_text="T6 shards",width=100)
entry_t6_shards.place(x = 380 , y = 135)
entry_t7_runes = customtkinter.CTkEntry(Prices_frame, placeholder_text="T7 runes",width=100)
entry_t7_runes.place(x = 20 , y = 175)
entry_t7_souls = customtkinter.CTkEntry(Prices_frame, placeholder_text="T7 souls",width=100)
entry_t7_souls.place(x = 140 , y = 175)
entry_t7_relics = customtkinter.CTkEntry(Prices_frame, placeholder_text="T7 relics",width=100)
entry_t7_relics.place(x = 260 , y = 175)
entry_t7_shards = customtkinter.CTkEntry(Prices_frame, placeholder_text="T7 shards",width=100)
entry_t7_shards.place(x = 380 , y = 175)
entry_t8_runes = customtkinter.CTkEntry(Prices_frame, placeholder_text="T8 runes",width=100)
entry_t8_runes.place(x = 20 , y = 215)
entry_t8_souls = customtkinter.CTkEntry(Prices_frame, placeholder_text="T8 souls",width=100)
entry_t8_souls.place(x = 140 , y = 215)
entry_t8_relics = customtkinter.CTkEntry(Prices_frame, placeholder_text="T8 relics",width=100)
entry_t8_relics.place(x = 260 , y = 215)
entry_t8_shards = customtkinter.CTkEntry(Prices_frame, placeholder_text="T8 shards",width=100)
entry_t8_shards.place(x = 380 , y = 215)
entry_tax_rate = customtkinter.CTkEntry(misc_frame, placeholder_text="Tax rate (%)",width=125)
entry_tax_rate.place(x = 70, y = 10 )
entry_profit_margin = customtkinter.CTkEntry(misc_frame, placeholder_text="Profit Margin(%)",width=104)
entry_profit_margin.place(x = 90, y = 50)
btn = customtkinter.CTkButton(misc_frame, text="START",command=lambda: mp.Process(target=main,args=(btn,)).start(),fg_color="green",font=('Helvetica', 18, 'bold'))
btn.place(x = 30 , y = 90)
app.mainloop()
Traceback (most recent call last):
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "C:\Users\pc\Desktop\code\program 2.0\venv002\Lib\site-packages\customtkinter\windows\widgets\ctk_button.py", line 554, in _clicked
self._command()
File "c:\Users\pc\Desktop\code\program 2.0\test.py", line 138, in <lambda>
btn = customtkinter.CTkButton(misc_frame, text="START",command=lambda: mp.Process(target=main,args=(btn,)).start(),fg_color="green",font=('Helvetica', 18, 'bold'))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
^^^^^^^^^^^^^^^^^
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\context.py", line 336, in _Popen
return Popen(process_obj)
^^^^^^^^^^^^^^^^^^
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\popen_spawn_win32.py", line 94, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_tkinter.tkapp' object
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 122, in spawn_main
exitcode = _main(fd, parent_sentinel)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\pc\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 132, in _main
self = reduction.pickle.load(from_parent)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
EOFError: Ran out of input
tkinter
widgets cannot be shared across processes, so you need to disable and enable the button in current process. You can use .after()
to check periodically whether the child process has finished or not.
Below is an example:
# function to be executed in child process
def main():
import time
for i in range(10):
print("hello")
time.sleep(1)
print("done")
if __name__ == "__main__":
import customtkinter as ctk
import multiprocessing as mp
def start(btn):
# disable the button
btn.configure(state="disabled", fg_color="red", text="Running")
# start the child process
p = mp.Process(target=main)
p.start()
# function to check whether child process has terminated or not
def wait_for_process():
if p.is_alive():
# child process is still running, schedule next checking
btn.after(100, wait_for_process)
else:
# child process has terminated, enable the button
btn.configure(state="normal", text="START", fg_color="green")
# start the periodic checking
wait_for_process()
root = ctk.CTk()
btn = ctk.CTkButton(root, text="START", fg_color="green",
font=("Helvetica", 18, "bold"),
command=lambda: start(btn))
btn.pack()
root.mainloop()