I found a way to compile Python files that use customtkinter in one-file mode using Pyinstaller
Hey Tom,
I found a way you can use to create a program that uses customtkinter in --one-file mode using pyinstaller.
The solution is by inserting this piece of code at the beginning of the python file you want to compile:
# imports necessary to get the path where the files are extracted in
import os
import sys
# initializing a variable containing the path where application files are stored.
application_path = ''
# attempting to get where the program files are stored
if getattr(sys, 'frozen', False):
# if program was frozen (compiled) using pyinstaller, the pyinstaller bootloader creates a sys attribute
# frozen=True to indicate that the script file was compiled using pyinstaller, then it creates a
# constant in sys that points to the directory where program executable is (where program files are extracted in).
application_path = sys._MEIPASS
else:
# if program is not frozen (compiled) using pyinstaller and is running normally like a Python 3.x.x file.
application_path = os.path.dirname(os.path.abspath(__file__))
# changing the current working directory to the path where one-file mode source files are extracted in.
os.chdir(application_path)
# importing customtkinter
from customtkinter import *
-
By changing the current working directory of the program's process (
os.chdir()), You change the directory where Python interpreter will search for the files of thecustomtkinterframework, Which will of course be the directory where the pyinstaller's bootloader will extract the files (the files added using the option--add-data) in. - If it doesn't seem to work, you can also append the
application_pathto the end of thesys.pathlist, by adding this line:sys.path.append(application_path)beforefrom customtkinter import *, this also happens to solve some issues if theos.chdir(application_path)doesn't seem to be changing the cwd or if it got changed by another function in the code.
Hey @InsertX2k , I tried out your solution and was wondering if you could give me a hand. I added the piece of code you posted and im still having issues with pyinstalled/autopytoexe.
Thanks!
Hey @InsertX2k , I tried out your solution and was wondering if you could give me a hand. I added the piece of code you posted and im still having issues with pyinstalled/autopytoexe.
Thanks!
Possibly an issue with another import/module, Can you include more details? (anything that might be useful in identifying the issue, like the output of the pyinstaller compilation command, or what exactly was the error you saw).
Hi @InsertX2k
(I am entirely new to Python and still learning so bear with me)
I have tried to use your code but it fails on me when i use it together with the https://github.com/TomSchimansky/CustomTkinter/blob/master/examples/complex_example.py
-
So basically i have put your code on the top and then copied the code from complex.example.py
-
I then go to command prompt to activate my environment: ....PycharmProjects\customtkinter_venv\venv\Scripts\activate.bat
-
I go back to: PycharmProjects\customtkinter_venv\
-
Using the following command "Pyinstaller --onefile tkintercust.py" (it seems to generate a file without a problem in my dist-folder
-
Try to run the tkintercust.exe
Result:
(venv) C:\Users\123455\PycharmProjects\customtkinter_venv\dist>tkintercust.exe
Traceback (most recent call last):
File "tkintercust.py", line 22, in
- I then tried to disable the code on line 22: #from customtkinter import *
- compiled again with "Pyinstaller --onefile tkintercust.py"
- Now the result was different:
PycharmProjects\customtkinter_venv\dist>tkintercust.exe
Traceback (most recent call last):
File "tkintercust.py", line 26, in
Everything runs fine when i run directly from PyCharm.
My complete code is attached below. Unfortunately since i am in the learning process i am sort of in a teaspoon-mode right now :-D
Any suggestion or do you have a full example of your code that works with customtkinter?
# imports necessary to get the path where the files are extracted in
import os
import sys
# initializing a variable containing the path where application files are stored.
application_path = ''
# attempting to get where the program files are stored
if getattr(sys, 'frozen', False):
# if program was frozen (compiled) using pyinstaller, the pyinstaller bootloader creates a sys attribute
# frozen=True to indicate that the script file was compiled using pyinstaller, then it creates a
# constant in sys that points to the directory where program executable is (where program files are extracted in).
application_path = sys._MEIPASS
else:
# if program is not frozen (compiled) using pyinstaller and is running normally like a Python 3.x.x file.
application_path = os.path.dirname(os.path.abspath(__file__))
# changing the current working directory to the path where one-file mode source files are extracted in.
os.chdir(application_path)
# importing customtkinter
from customtkinter import *
import tkinter
import tkinter.messagebox
import customtkinter
customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue"
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
# configure window
self.title("CustomTkinter complex_example.py")
self.geometry(f"{1100}x{580}")
# configure grid layout (4x4)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure((2, 3), weight=0)
self.grid_rowconfigure((0, 1, 2), weight=1)
# create sidebar frame with widgets
self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0)
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew")
self.sidebar_frame.grid_rowconfigure(4, weight=1)
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CustomTkinter", font=customtkinter.CTkFont(size=20, weight="bold"))
self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))
self.sidebar_button_1 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event)
self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10)
self.sidebar_button_2 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event)
self.sidebar_button_2.grid(row=2, column=0, padx=20, pady=10)
self.sidebar_button_3 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event)
self.sidebar_button_3.grid(row=3, column=0, padx=20, pady=10)
self.appearance_mode_label = customtkinter.CTkLabel(self.sidebar_frame, text="Appearance Mode:", anchor="w")
self.appearance_mode_label.grid(row=5, column=0, padx=20, pady=(10, 0))
self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"],
command=self.change_appearance_mode_event)
self.appearance_mode_optionemenu.grid(row=6, column=0, padx=20, pady=(10, 10))
self.scaling_label = customtkinter.CTkLabel(self.sidebar_frame, text="UI Scaling:", anchor="w")
self.scaling_label.grid(row=7, column=0, padx=20, pady=(10, 0))
self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["80%", "90%", "100%", "110%", "120%"],
command=self.change_scaling_event)
self.scaling_optionemenu.grid(row=8, column=0, padx=20, pady=(10, 20))
# create main entry and button
self.entry = customtkinter.CTkEntry(self, placeholder_text="CTkEntry")
self.entry.grid(row=3, column=1, columnspan=2, padx=(20, 0), pady=(20, 20), sticky="nsew")
self.main_button_1 = customtkinter.CTkButton(master=self, fg_color="transparent", border_width=2, text_color=("gray10", "#DCE4EE"))
self.main_button_1.grid(row=3, column=3, padx=(20, 20), pady=(20, 20), sticky="nsew")
# create textbox
self.textbox = customtkinter.CTkTextbox(self, width=250)
self.textbox.grid(row=0, column=1, padx=(20, 0), pady=(20, 0), sticky="nsew")
# create tabview
self.tabview = customtkinter.CTkTabview(self, width=250)
self.tabview.grid(row=0, column=2, padx=(20, 0), pady=(20, 0), sticky="nsew")
self.tabview.add("CTkTabview")
self.tabview.add("Tab 2")
self.tabview.add("Tab 3")
self.tabview.tab("CTkTabview").grid_columnconfigure(0, weight=1) # configure grid of individual tabs
self.tabview.tab("Tab 2").grid_columnconfigure(0, weight=1)
self.optionmenu_1 = customtkinter.CTkOptionMenu(self.tabview.tab("CTkTabview"), dynamic_resizing=False,
values=["Value 1", "Value 2", "Value Long Long Long"])
self.optionmenu_1.grid(row=0, column=0, padx=20, pady=(20, 10))
self.combobox_1 = customtkinter.CTkComboBox(self.tabview.tab("CTkTabview"),
values=["Value 1", "Value 2", "Value Long....."])
self.combobox_1.grid(row=1, column=0, padx=20, pady=(10, 10))
self.string_input_button = customtkinter.CTkButton(self.tabview.tab("CTkTabview"), text="Open CTkInputDialog",
command=self.open_input_dialog_event)
self.string_input_button.grid(row=2, column=0, padx=20, pady=(10, 10))
self.label_tab_2 = customtkinter.CTkLabel(self.tabview.tab("Tab 2"), text="CTkLabel on Tab 2")
self.label_tab_2.grid(row=0, column=0, padx=20, pady=20)
# create radiobutton frame
self.radiobutton_frame = customtkinter.CTkFrame(self)
self.radiobutton_frame.grid(row=0, column=3, padx=(20, 20), pady=(20, 0), sticky="nsew")
self.radio_var = tkinter.IntVar(value=0)
self.label_radio_group = customtkinter.CTkLabel(master=self.radiobutton_frame, text="CTkRadioButton Group:")
self.label_radio_group.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="")
self.radio_button_1 = customtkinter.CTkRadioButton(master=self.radiobutton_frame, variable=self.radio_var, value=0)
self.radio_button_1.grid(row=1, column=2, pady=10, padx=20, sticky="n")
self.radio_button_2 = customtkinter.CTkRadioButton(master=self.radiobutton_frame, variable=self.radio_var, value=1)
self.radio_button_2.grid(row=2, column=2, pady=10, padx=20, sticky="n")
self.radio_button_3 = customtkinter.CTkRadioButton(master=self.radiobutton_frame, variable=self.radio_var, value=2)
self.radio_button_3.grid(row=3, column=2, pady=10, padx=20, sticky="n")
# create slider and progressbar frame
self.slider_progressbar_frame = customtkinter.CTkFrame(self, fg_color="transparent")
self.slider_progressbar_frame.grid(row=1, column=1, padx=(20, 0), pady=(20, 0), sticky="nsew")
self.slider_progressbar_frame.grid_columnconfigure(0, weight=1)
self.slider_progressbar_frame.grid_rowconfigure(4, weight=1)
self.seg_button_1 = customtkinter.CTkSegmentedButton(self.slider_progressbar_frame)
self.seg_button_1.grid(row=0, column=0, padx=(20, 10), pady=(10, 10), sticky="ew")
self.progressbar_1 = customtkinter.CTkProgressBar(self.slider_progressbar_frame)
self.progressbar_1.grid(row=1, column=0, padx=(20, 10), pady=(10, 10), sticky="ew")
self.progressbar_2 = customtkinter.CTkProgressBar(self.slider_progressbar_frame)
self.progressbar_2.grid(row=2, column=0, padx=(20, 10), pady=(10, 10), sticky="ew")
self.slider_1 = customtkinter.CTkSlider(self.slider_progressbar_frame, from_=0, to=1, number_of_steps=4)
self.slider_1.grid(row=3, column=0, padx=(20, 10), pady=(10, 10), sticky="ew")
self.slider_2 = customtkinter.CTkSlider(self.slider_progressbar_frame, orientation="vertical")
self.slider_2.grid(row=0, column=1, rowspan=5, padx=(10, 10), pady=(10, 10), sticky="ns")
self.progressbar_3 = customtkinter.CTkProgressBar(self.slider_progressbar_frame, orientation="vertical")
self.progressbar_3.grid(row=0, column=2, rowspan=5, padx=(10, 20), pady=(10, 10), sticky="ns")
# create scrollable frame
self.scrollable_frame = customtkinter.CTkScrollableFrame(self, label_text="CTkScrollableFrame")
self.scrollable_frame.grid(row=1, column=2, padx=(20, 0), pady=(20, 0), sticky="nsew")
self.scrollable_frame.grid_columnconfigure(0, weight=1)
self.scrollable_frame_switches = []
for i in range(100):
switch = customtkinter.CTkSwitch(master=self.scrollable_frame, text=f"CTkSwitch {i}")
switch.grid(row=i, column=0, padx=10, pady=(0, 20))
self.scrollable_frame_switches.append(switch)
# create checkbox and switch frame
self.checkbox_slider_frame = customtkinter.CTkFrame(self)
self.checkbox_slider_frame.grid(row=1, column=3, padx=(20, 20), pady=(20, 0), sticky="nsew")
self.checkbox_1 = customtkinter.CTkCheckBox(master=self.checkbox_slider_frame)
self.checkbox_1.grid(row=1, column=0, pady=(20, 0), padx=20, sticky="n")
self.checkbox_2 = customtkinter.CTkCheckBox(master=self.checkbox_slider_frame)
self.checkbox_2.grid(row=2, column=0, pady=(20, 0), padx=20, sticky="n")
self.checkbox_3 = customtkinter.CTkCheckBox(master=self.checkbox_slider_frame)
self.checkbox_3.grid(row=3, column=0, pady=20, padx=20, sticky="n")
# set default values
self.sidebar_button_3.configure(state="disabled", text="Disabled CTkButton")
self.checkbox_3.configure(state="disabled")
self.checkbox_1.select()
self.scrollable_frame_switches[0].select()
self.scrollable_frame_switches[4].select()
self.radio_button_3.configure(state="disabled")
self.appearance_mode_optionemenu.set("Dark")
self.scaling_optionemenu.set("100%")
self.optionmenu_1.set("CTkOptionmenu")
self.combobox_1.set("CTkComboBox")
self.slider_1.configure(command=self.progressbar_2.set)
self.slider_2.configure(command=self.progressbar_3.set)
self.progressbar_1.configure(mode="indeterminnate")
self.progressbar_1.start()
self.textbox.insert("0.0", "CTkTextbox\n\n" + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.\n\n" * 20)
self.seg_button_1.configure(values=["CTkSegmentedButton", "Value 2", "Value 3"])
self.seg_button_1.set("Value 2")
def open_input_dialog_event(self):
dialog = customtkinter.CTkInputDialog(text="Type in a number:", title="CTkInputDialog")
print("CTkInputDialog:", dialog.get_input())
def change_appearance_mode_event(self, new_appearance_mode: str):
customtkinter.set_appearance_mode(new_appearance_mode)
def change_scaling_event(self, new_scaling: str):
new_scaling_float = int(new_scaling.replace("%", "")) / 100
customtkinter.set_widget_scaling(new_scaling_float)
def sidebar_button_event(self):
print("sidebar_button click")
if __name__ == "__main__":
app = App()
app.mainloop()
Hi @InsertX2k
(I am entirely new to Python and still learning so bear with me)
I have tried to use your code but it fails on me when i use it together with the https://github.com/TomSchimansky/CustomTkinter/blob/master/examples/complex_example.py
So basically i have put your code on the top and then copied the code from complex.example.py
I then go to command prompt to activate my environment: ....PycharmProjects\customtkinter_venv\venv\Scripts\activate.bat
I go back to: PycharmProjects\customtkinter_venv\
Using the following command "Pyinstaller --onefile tkintercust.py" (it seems to generate a file without a problem in my dist-folder
Try to run the tkintercust.exe
Result: (venv) C:\Users\123455\PycharmProjects\customtkinter_venv\dist>tkintercust.exe Traceback (most recent call last): File "tkintercust.py", line 22, in
ModuleNotFoundError: No module named 'customtkinter' [1612] Failed to execute script 'tkintercust' due to unhandled exception!
- I then tried to disable the code on line 22: #from customtkinter import *
- compiled again with "Pyinstaller --onefile tkintercust.py"
- Now the result was different:
PycharmProjects\customtkinter_venv\dist>tkintercust.exe Traceback (most recent call last): File "tkintercust.py", line 26, in
ModuleNotFoundError: No module named 'customtkinter' [8040] Failed to execute script 'tkintercust' due to unhandled exception! Everything runs fine when i run directly from PyCharm.
My complete code is attached below. Unfortunately since i am in the learning process i am sort of in a teaspoon-mode right now :-D
Any suggestion or do you have a full example of your code that works with customtkinter?
# imports necessary to get the path where the files are extracted in import os import sys # initializing a variable containing the path where application files are stored. application_path = '' # attempting to get where the program files are stored if getattr(sys, 'frozen', False): # if program was frozen (compiled) using pyinstaller, the pyinstaller bootloader creates a sys attribute # frozen=True to indicate that the script file was compiled using pyinstaller, then it creates a # constant in sys that points to the directory where program executable is (where program files are extracted in). application_path = sys._MEIPASS else: # if program is not frozen (compiled) using pyinstaller and is running normally like a Python 3.x.x file. application_path = os.path.dirname(os.path.abspath(__file__)) # changing the current working directory to the path where one-file mode source files are extracted in. os.chdir(application_path) # importing customtkinter from customtkinter import * import tkinter import tkinter.messagebox import customtkinter customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light" customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue" class App(customtkinter.CTk): def __init__(self): super().__init__() # configure window self.title("CustomTkinter complex_example.py") self.geometry(f"{1100}x{580}") # configure grid layout (4x4) self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure((2, 3), weight=0) self.grid_rowconfigure((0, 1, 2), weight=1) # create sidebar frame with widgets self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0) self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew") self.sidebar_frame.grid_rowconfigure(4, weight=1) self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="CustomTkinter", font=customtkinter.CTkFont(size=20, weight="bold")) self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10)) self.sidebar_button_1 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event) self.sidebar_button_1.grid(row=1, column=0, padx=20, pady=10) self.sidebar_button_2 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event) self.sidebar_button_2.grid(row=2, column=0, padx=20, pady=10) self.sidebar_button_3 = customtkinter.CTkButton(self.sidebar_frame, command=self.sidebar_button_event) self.sidebar_button_3.grid(row=3, column=0, padx=20, pady=10) self.appearance_mode_label = customtkinter.CTkLabel(self.sidebar_frame, text="Appearance Mode:", anchor="w") self.appearance_mode_label.grid(row=5, column=0, padx=20, pady=(10, 0)) self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"], command=self.change_appearance_mode_event) self.appearance_mode_optionemenu.grid(row=6, column=0, padx=20, pady=(10, 10)) self.scaling_label = customtkinter.CTkLabel(self.sidebar_frame, text="UI Scaling:", anchor="w") self.scaling_label.grid(row=7, column=0, padx=20, pady=(10, 0)) self.scaling_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["80%", "90%", "100%", "110%", "120%"], command=self.change_scaling_event) self.scaling_optionemenu.grid(row=8, column=0, padx=20, pady=(10, 20)) # create main entry and button self.entry = customtkinter.CTkEntry(self, placeholder_text="CTkEntry") self.entry.grid(row=3, column=1, columnspan=2, padx=(20, 0), pady=(20, 20), sticky="nsew") self.main_button_1 = customtkinter.CTkButton(master=self, fg_color="transparent", border_width=2, text_color=("gray10", "#DCE4EE")) self.main_button_1.grid(row=3, column=3, padx=(20, 20), pady=(20, 20), sticky="nsew") # create textbox self.textbox = customtkinter.CTkTextbox(self, width=250) self.textbox.grid(row=0, column=1, padx=(20, 0), pady=(20, 0), sticky="nsew") # create tabview self.tabview = customtkinter.CTkTabview(self, width=250) self.tabview.grid(row=0, column=2, padx=(20, 0), pady=(20, 0), sticky="nsew") self.tabview.add("CTkTabview") self.tabview.add("Tab 2") self.tabview.add("Tab 3") self.tabview.tab("CTkTabview").grid_columnconfigure(0, weight=1) # configure grid of individual tabs self.tabview.tab("Tab 2").grid_columnconfigure(0, weight=1) self.optionmenu_1 = customtkinter.CTkOptionMenu(self.tabview.tab("CTkTabview"), dynamic_resizing=False, values=["Value 1", "Value 2", "Value Long Long Long"]) self.optionmenu_1.grid(row=0, column=0, padx=20, pady=(20, 10)) self.combobox_1 = customtkinter.CTkComboBox(self.tabview.tab("CTkTabview"), values=["Value 1", "Value 2", "Value Long....."]) self.combobox_1.grid(row=1, column=0, padx=20, pady=(10, 10)) self.string_input_button = customtkinter.CTkButton(self.tabview.tab("CTkTabview"), text="Open CTkInputDialog", command=self.open_input_dialog_event) self.string_input_button.grid(row=2, column=0, padx=20, pady=(10, 10)) self.label_tab_2 = customtkinter.CTkLabel(self.tabview.tab("Tab 2"), text="CTkLabel on Tab 2") self.label_tab_2.grid(row=0, column=0, padx=20, pady=20) # create radiobutton frame self.radiobutton_frame = customtkinter.CTkFrame(self) self.radiobutton_frame.grid(row=0, column=3, padx=(20, 20), pady=(20, 0), sticky="nsew") self.radio_var = tkinter.IntVar(value=0) self.label_radio_group = customtkinter.CTkLabel(master=self.radiobutton_frame, text="CTkRadioButton Group:") self.label_radio_group.grid(row=0, column=2, columnspan=1, padx=10, pady=10, sticky="") self.radio_button_1 = customtkinter.CTkRadioButton(master=self.radiobutton_frame, variable=self.radio_var, value=0) self.radio_button_1.grid(row=1, column=2, pady=10, padx=20, sticky="n") self.radio_button_2 = customtkinter.CTkRadioButton(master=self.radiobutton_frame, variable=self.radio_var, value=1) self.radio_button_2.grid(row=2, column=2, pady=10, padx=20, sticky="n") self.radio_button_3 = customtkinter.CTkRadioButton(master=self.radiobutton_frame, variable=self.radio_var, value=2) self.radio_button_3.grid(row=3, column=2, pady=10, padx=20, sticky="n") # create slider and progressbar frame self.slider_progressbar_frame = customtkinter.CTkFrame(self, fg_color="transparent") self.slider_progressbar_frame.grid(row=1, column=1, padx=(20, 0), pady=(20, 0), sticky="nsew") self.slider_progressbar_frame.grid_columnconfigure(0, weight=1) self.slider_progressbar_frame.grid_rowconfigure(4, weight=1) self.seg_button_1 = customtkinter.CTkSegmentedButton(self.slider_progressbar_frame) self.seg_button_1.grid(row=0, column=0, padx=(20, 10), pady=(10, 10), sticky="ew") self.progressbar_1 = customtkinter.CTkProgressBar(self.slider_progressbar_frame) self.progressbar_1.grid(row=1, column=0, padx=(20, 10), pady=(10, 10), sticky="ew") self.progressbar_2 = customtkinter.CTkProgressBar(self.slider_progressbar_frame) self.progressbar_2.grid(row=2, column=0, padx=(20, 10), pady=(10, 10), sticky="ew") self.slider_1 = customtkinter.CTkSlider(self.slider_progressbar_frame, from_=0, to=1, number_of_steps=4) self.slider_1.grid(row=3, column=0, padx=(20, 10), pady=(10, 10), sticky="ew") self.slider_2 = customtkinter.CTkSlider(self.slider_progressbar_frame, orientation="vertical") self.slider_2.grid(row=0, column=1, rowspan=5, padx=(10, 10), pady=(10, 10), sticky="ns") self.progressbar_3 = customtkinter.CTkProgressBar(self.slider_progressbar_frame, orientation="vertical") self.progressbar_3.grid(row=0, column=2, rowspan=5, padx=(10, 20), pady=(10, 10), sticky="ns") # create scrollable frame self.scrollable_frame = customtkinter.CTkScrollableFrame(self, label_text="CTkScrollableFrame") self.scrollable_frame.grid(row=1, column=2, padx=(20, 0), pady=(20, 0), sticky="nsew") self.scrollable_frame.grid_columnconfigure(0, weight=1) self.scrollable_frame_switches = [] for i in range(100): switch = customtkinter.CTkSwitch(master=self.scrollable_frame, text=f"CTkSwitch {i}") switch.grid(row=i, column=0, padx=10, pady=(0, 20)) self.scrollable_frame_switches.append(switch) # create checkbox and switch frame self.checkbox_slider_frame = customtkinter.CTkFrame(self) self.checkbox_slider_frame.grid(row=1, column=3, padx=(20, 20), pady=(20, 0), sticky="nsew") self.checkbox_1 = customtkinter.CTkCheckBox(master=self.checkbox_slider_frame) self.checkbox_1.grid(row=1, column=0, pady=(20, 0), padx=20, sticky="n") self.checkbox_2 = customtkinter.CTkCheckBox(master=self.checkbox_slider_frame) self.checkbox_2.grid(row=2, column=0, pady=(20, 0), padx=20, sticky="n") self.checkbox_3 = customtkinter.CTkCheckBox(master=self.checkbox_slider_frame) self.checkbox_3.grid(row=3, column=0, pady=20, padx=20, sticky="n") # set default values self.sidebar_button_3.configure(state="disabled", text="Disabled CTkButton") self.checkbox_3.configure(state="disabled") self.checkbox_1.select() self.scrollable_frame_switches[0].select() self.scrollable_frame_switches[4].select() self.radio_button_3.configure(state="disabled") self.appearance_mode_optionemenu.set("Dark") self.scaling_optionemenu.set("100%") self.optionmenu_1.set("CTkOptionmenu") self.combobox_1.set("CTkComboBox") self.slider_1.configure(command=self.progressbar_2.set) self.slider_2.configure(command=self.progressbar_3.set) self.progressbar_1.configure(mode="indeterminnate") self.progressbar_1.start() self.textbox.insert("0.0", "CTkTextbox\n\n" + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.\n\n" * 20) self.seg_button_1.configure(values=["CTkSegmentedButton", "Value 2", "Value 3"]) self.seg_button_1.set("Value 2") def open_input_dialog_event(self): dialog = customtkinter.CTkInputDialog(text="Type in a number:", title="CTkInputDialog") print("CTkInputDialog:", dialog.get_input()) def change_appearance_mode_event(self, new_appearance_mode: str): customtkinter.set_appearance_mode(new_appearance_mode) def change_scaling_event(self, new_scaling: str): new_scaling_float = int(new_scaling.replace("%", "")) / 100 customtkinter.set_widget_scaling(new_scaling_float) def sidebar_button_event(self): print("sidebar_button click") if __name__ == "__main__": app = App() app.mainloop()
Hi, it's okay we all are still learning, anyway you could have just installed customtkinter using pip and it will fix this problem.
Thank you for such quick response, i really appreciate that.
At first i thought i did not have it installed, but i do:
\PycharmProjects\customtkinter_venv>pip list Package Version
customtkinter 5.2.0 darkdetect 0.8.0 pip 23.2.1 setuptools 68.1.2 tk 0.1.0 wheel 0.41.2
So it seems that if i include:
from customtkinter import *
I get the following error message: \PycharmProjects\customtkinter_venv\dist>tkintercust.exe Traceback (most recent call last): File "tkintercust.py", line 22, in ModuleNotFoundError: No module named 'customtkinter' [1612] Failed to execute script 'tkintercust' due to unhandled exception!
If i comment it out: #from customtkinter import *
I get:
PycharmProjects\customtkinter_venv\dist>tkintercust.exe
Traceback (most recent call last):
File "tkintercust.py", line 26, in
I made the simplest program (one textbox and one button) i could think of utilizing customtkinter and included your code at the top:
I ran it with pyinstaller --onefile simple.py Result, did not work.
I tried also a bit more extensive command, but it didnt work either: pyinstaller --onefile --add-data "C:\Users\123456\PycharmProjects\customtkinter_venv\venv\Lib\site-packages\customtkinter;customtkinter" --hidden-import distutils --hidden-import tkinter.font --hidden-import darkdetect --additional-hooks-dir=. simple.py
# imports necessary to get the path where the files are extracted in
import os
import sys
# initializing a variable containing the path where application files are stored.
application_path = ''
# attempting to get where the program files are stored
if getattr(sys, 'frozen', False):
# if program was frozen (compiled) using pyinstaller, the pyinstaller bootloader creates a sys attribute
# frozen=True to indicate that the script file was compiled using pyinstaller, then it creates a
# constant in sys that points to the directory where program executable is (where program files are extracted in).
application_path = sys._MEIPASS
else:
# if program is not frozen (compiled) using pyinstaller and is running normally like a Python 3.x.x file.
application_path = os.path.dirname(os.path.abspath(__file__))
# changing the current working directory to the path where one-file mode source files are extracted in.
os.chdir(application_path)
# importing customtkinter
from customtkinter import *
import tkinter as tk
import customtkinter as ctk
# Explicitly import tkinter.filedialog
import tkinter.filedialog
class SimpleApp(ctk.CTk):
def __init__(self):
super().__init__()
# Set up the window
self.title("Simple CustomTkinter App")
self.geometry("400x200")
# Create a text box
self.text_box = ctk.CTkEntry(self, placeholder_text="Enter text here...")
self.text_box.pack(pady=20)
# Create a button
self.button = ctk.CTkButton(self, text="Submit", command=self.submit)
self.button.pack()
def submit(self):
# Get the text from the text box and display it
text = self.text_box.get()
ctk.CTkMessageBox.showinfo("Message", f"You entered: {text}")
if __name__ == "__main__":
app = SimpleApp()
app.mainloop()
Try this and see if it works
# imports necessary to get the path where the files are extracted in
import os
import sys
# initializing a variable containing the path where application files are stored.
application_path = ''
# attempting to get where the program files are stored
if getattr(sys, 'frozen', False):
# if program was frozen (compiled) using pyinstaller, the pyinstaller bootloader creates a sys attribute
# frozen=True to indicate that the script file was compiled using pyinstaller, then it creates a
# constant in sys that points to the directory where program executable is (where program files are extracted in).
application_path = sys._MEIPASS
else:
# if program is not frozen (compiled) using pyinstaller and is running normally like a Python 3.x.x file.
application_path = os.path.dirname(os.path.abspath(__file__))
import tkinter as tk
import customtkinter as ctk
# Explicitly import tkinter.filedialog
import tkinter.filedialog
class SimpleApp(ctk.CTk):
def __init__(self):
super().__init__()
# Set up the window
self.title("Simple CustomTkinter App")
self.geometry("400x200")
# Create a text box
self.text_box = ctk.CTkEntry(self, placeholder_text="Enter text here...")
self.text_box.pack(pady=20)
# Create a button
self.button = ctk.CTkButton(self, text="Submit", command=self.submit)
self.button.pack()
def submit(self):
# Get the text from the text box and display it
text = self.text_box.get()
ctk.CTkMessageBox.showinfo("Message", f"You entered: {text}")
if __name__ == "__main__":
# changing the current working directory to the path where one-file mode source files are extracted in.
os.chdir(application_path)
app = SimpleApp()
app.mainloop()
Then be sure to include the files of customtkinter using --add-data option, and be sure to use --hidden-import with customtkinter like this --hidden-import customtkinter
Didnt work for me, it still fails with the previous error message:
PycharmProjects\customtkinter_venv\dist>test3.exe
Traceback (most recent call last):
File "test3.py", line 22, in
Didnt work for me, it still fails with the previous error message:
PycharmProjects\customtkinter_venv\dist>test3.exe Traceback (most recent call last): File "test3.py", line 22, in
ModuleNotFoundError: No module named 'customtkinter' [14484] Failed to execute script 'test3' due to unhandled exception!
Possibly it is an issue with your virtual environment, Have you tried the code without using a virtual environment?
Try this pyinstaller --onefile --windowed --add-data "C:\Python313\Lib\site-packages\customtkinter;customtkinter" --hidden-import customtkinter .\yourProject.py
Select your version Python path "C:\Python313"
Try this pyinstaller --onefile --windowed --add-data "C:\Python313\Lib\site-packages\customtkinter;customtkinter" --hidden-import customtkinter .\yourProject.py
Select your version Python path "C:\Python313"
yes probably the issue was with the command line he used to compile his python script using.