My project runs with no problems in PyCharm, but when I create an executable I get this error.
Exception in Tkinter callback
Traceback (most recent call last):
File "tkinter_`_`init`_`_.py", line 1968, in `__`call`__
File "meet_systems_main.py", line 165, in open_athletes
File "subprocess.py", line 1026, in `__`init`__
File "subprocess.py", line 1538, in _execute_child
FileNotFoundError: [WinError 2] The system cannot find the file specified
video of error https://meetsystems.org/2024-09-09_17-28-23.mp4
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import os
import sys
import sqlite3
import subprocess
# Global variable to store the selected database file path
global_db_file_path = None
# Function to find the correct path for the image, even when bundled
def resource_path(relative_path):
""" Get the absolute path to the resource, works for dev and PyInstaller """
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# Reusable function to create tables
def create_table(cursor, table_name, columns):
""" Generic function to create a table """
query = f"CREATE TABLE IF NOT EXISTS {table_name} ({columns})"
cursor.execute(query)
# Function to create the SQLite database and tables
def create_database(file_path):
conn = sqlite3.connect(file_path)
cursor = conn.cursor()
# Create the 'athletes' table
create_table(cursor, 'athletes', '''
id INTEGER PRIMARY KEY AUTOINCREMENT,
age INTEGER,
team_id STRING,
team_name STRING,
last_name STRING,
first_name STRING,
middle_initials STRING,
dob DATETIME,
gender STRING,
bib_number INTEGER,
membership_number STRING
''')
# Create the 'team' table
create_table(cursor, 'teams', '''
id INTEGER PRIMARY KEY AUTOINCREMENT,
team_name TEXT,
team_code TEXT
''')
# Create the 'division' table
create_table(cursor, 'division', '''
id INTEGER PRIMARY KEY AUTOINCREMENT,
division_number STRING,
division_abbr STRING,
division_name STRING,
low_age INTEGER,
high_age INTEGER,
age_as_of_date DATETIME
''')
conn.commit()
conn.close()
print(f"Database created successfully at: {file_path}")
# Function to open and display the tables in the selected database
def open_database():
global global_db_file_path # Access the global variable
file_path = filedialog.askopenfilename(defaultextension=".db",
filetypes=[("SQLite Database", "*.db")],
title="Select a database to open")
if not file_path:
return # User canceled the file dialog
try:
conn = sqlite3.connect(file_path)
cursor = conn.cursor()
# Query to get all table names from the SQLite master table
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()
if not tables:
messagebox.showinfo("Info", "No tables found in the database.")
else:
table_names = "n".join([table[0] for table in tables])
messagebox.showinfo("Tables in Database", f"Tables found:n{table_names}")
conn.close()
open_db_label.config(text=f"Opened Database: {os.path.basename(file_path)}")
# Set the global variable with the file path
global_db_file_path = file_path
except sqlite3.Error as e:
messagebox.showerror("Error", f"Failed to open the database. Error: {str(e)}")
# Function to open the 'Meet Setup' popup
def open_meet_setup():
popup = tk.Toplevel(root)
popup.title("Meet Setup")
popup.geometry("300x150")
tk.Label(popup, text="Meet Name:").pack(pady=10)
meet_name_entry = tk.Entry(popup)
meet_name_entry.pack(pady=10)
def submit_meet_name():
meet_name = meet_name_entry.get().strip()
if not meet_name:
messagebox.showerror("Error", "Meet Name is required")
return
file_path = filedialog.asksaveasfilename(defaultextension=".db",
initialfile=f"{meet_name}.db",
filetypes=[("SQLite Database", "*.db")],
title="Select location to save database")
if file_path:
create_database(file_path)
popup.destroy()
submit_button = tk.Button(popup, text="Submit", command=submit_meet_name)
submit_button.pack(pady=10)
def open_athletes():
if global_db_file_path:
# Path to the Python executable in your virtual environment
python_executable = os.path.join(os.path.dirname(sys.executable), 'python.exe')
# Run the subprocess with the virtual environment's Python
subprocess.Popen([python_executable, 'athletes.py', global_db_file_path])
else:
messagebox.showwarning("Warning", "Please open a database first.")
def open_teams():
if global_db_file_path:
subprocess.Popen(['python', 'teams.py', global_db_file_path]) # Pass the DB path as an argument
else:
messagebox.showwarning("Warning", "Please open a database first.")
# Load image from the provided file path
IMAGE_PATH = resource_path("images/britanie.png")
# Create the main application window
root = tk.Tk()
root.title("Meet Systems Meet Manager")
root.geometry("1280x720")
# Load the background image and keep a reference to avoid garbage collection
image = Image.open(IMAGE_PATH)
bg_image = ImageTk.PhotoImage(image)
root.bg_image_ref = bg_image # Keep a reference to prevent garbage collection
# Create a label to hold the background image
bg_label = tk.Label(root, image=bg_image)
bg_label.place(x=0, y=0, relwidth=1, relheight=1)
# Create a label at the top to show which database is open
open_db_label = tk.Label(root, text="No Database Opened", font=("Helvetica", 14), bg='#ffffff', fg='#000000')
open_db_label.pack(pady=10, anchor="n")
# Add menu at the top of the window
menu_bar = tk.Menu(root)
file_menu = tk.Menu(menu_bar, tearoff=0)
file_menu.add_command(label="Meet Setup", command=open_meet_setup)
file_menu.add_command(label="Open Database", command=open_database)
file_menu.add_command(label="Division Setup")
file_menu.add_command(label="Event Setup")
file_menu.add_command(label="Athletes", command=open_athletes)
file_menu.add_command(label="Teams",command=open_teams)
file_menu.add_command(label="Seeding")
file_menu.add_command(label="Relays")
menu_bar.add_cascade(label="File", menu=file_menu)
# Add the menu to the window
root.config(menu=menu_bar)
# Add other widgets or content as needed below the menu
welcome_label = tk.Label(root, text="Meet Systems Meet Manager!", font=("Helvetica", 30), bg='#ffffff', fg='#000000')
welcome_label.pack(pady=100)
# Start the Tkinter main loop
root.mainloop()
import tkinter as tk
from tkinter import ttk
from tkcalendar import Calendar
import sqlite3
import sys
import os
#db_file_path = "G:\databasetest\runners.db"
# Helper function to connect to the database
def connect_db(db_file_path):
try:
return sqlite3.connect(db_file_path)
except sqlite3.Error as e:
print(f"Failed to connect to database: {e}")
sys.exit(1)
# Function to load athletes data into the table
def load_athletes_data(db_file_path):
try:
with connect_db(db_file_path) as conn:
cursor = conn.cursor()
cursor.execute(
"""SELECT last_name, first_name, middle_initials, gender, dob, team_id, team_name, bib_number, membership_number
FROM athletes;"""
)
athletes_data = cursor.fetchall()
# Clear existing data
for row in tree.get_children():
tree.delete(row)
# Insert data into Treeview
for athlete in athletes_data:
tree.insert("", "end", values=athlete)
except sqlite3.Error as e:
print(f"Failed to fetch data: {e}")
# Function to add a new athlete to the database
def add_athlete():
if not validate_inputs():
return
athlete_data = (
entry_last_name.get(),
entry_first_name.get(),
entry_mi.get(),
entry_gender.get(),
entry_dob.get(),
entry_team_id.get(),
entry_team_name.get(),
entry_bib_number.get(),
entry_membership_number.get(),
)
try:
with connect_db(db_file_path) as conn:
cursor = conn.cursor()
# Check for duplicates before adding the athlete
cursor.execute(
"SELECT * FROM athletes WHERE LOWER(last_name) = LOWER(?) AND LOWER(first_name) = LOWER(?) AND dob = ?",
(athlete_data[0], athlete_data[1], athlete_data[4])
)
if cursor.fetchone():
print("Athlete already exists in the database.")
return
cursor.execute(
"""INSERT INTO athletes (last_name, first_name, middle_initials, gender, dob, team_id, team_name, bib_number, membership_number)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
athlete_data
)
conn.commit()
# Clear input fields and refresh the Treeview with new data
clear_inputs()
load_athletes_data(db_file_path)
print("Athlete added successfully!")
except sqlite3.Error as e:
print(f"Failed to add athlete: {e}")
# Function to delete a selected athlete from the database
def delete_athlete():
selected_item = tree.selection()
if not selected_item:
print("Please select an athlete to delete.")
return
athlete = tree.item(selected_item, "values")
last_name, first_name, dob = athlete[0], athlete[1], athlete[4]
try:
with connect_db(db_file_path) as conn:
cursor = conn.cursor()
cursor.execute(
"DELETE FROM athletes WHERE last_name = ? AND first_name = ? AND dob = ?",
(last_name, first_name, dob)
)
conn.commit()
load_athletes_data(db_file_path)
print("Athlete deleted successfully!")
except sqlite3.Error as e:
print(f"Failed to delete athlete: {e}")
# Function to update an existing athlete's data
def update_athlete():
selected_item = tree.selection()
if not selected_item:
print("Please select an athlete to update.")
return
if not validate_inputs():
return
athlete_data = (
entry_mi.get(),
entry_gender.get(),
entry_dob.get(),
entry_team_id.get(),
entry_team_name.get(),
entry_bib_number.get(),
entry_membership_number.get(),
entry_last_name.get(),
entry_first_name.get(),
entry_dob.get(),
)
try:
with connect_db(db_file_path) as conn:
cursor = conn.cursor()
cursor.execute(
"""UPDATE athletes SET middle_initials = ?, gender = ?, dob = ?, team_id = ?, team_name = ?, bib_number = ?, membership_number = ?
WHERE last_name = ? AND first_name = ? AND dob = ?""",
athlete_data
)
conn.commit()
load_athletes_data(db_file_path)
print("Athlete updated successfully!")
except sqlite3.Error as e:
print(f"Failed to update athlete: {e}")
# Function to validate input fields before adding/updating an athlete
def validate_inputs():
if not entry_last_name.get() or not entry_first_name.get() or not entry_dob.get():
print("Last Name, First Name, and DOB are required.")
return False
return True
# Function to clear input fields
def clear_inputs():
entry_last_name.delete(0, tk.END)
entry_first_name.delete(0, tk.END)
entry_mi.delete(0, tk.END)
entry_gender.delete(0, tk.END)
entry_dob.delete(0, tk.END)
entry_team_id.delete(0, tk.END)
entry_team_name.delete(0, tk.END)
entry_bib_number.delete(0, tk.END)
entry_membership_number.delete(0, tk.END)
# Function to select an athlete in the Treeview
def select_athlete(event):
selected_item = tree.selection()
if selected_item:
athlete = tree.item(selected_item, "values")
# Populate the entry fields with the selected athlete's data
clear_inputs()
entry_last_name.insert(0, athlete[0])
entry_first_name.insert(0, athlete[1])
entry_mi.insert(0, athlete[2])
entry_gender.insert(0, athlete[3])
entry_dob.insert(0, athlete[4])
entry_team_id.insert(0, athlete[5])
entry_team_name.insert(0, athlete[6])
entry_bib_number.insert(0, athlete[7])
entry_membership_number.insert(0, athlete[8])
# Function to open the calendar popup
def open_calendar_popup():
def select_date():
selected_date = cal.selection_get()
print("Selected date:", selected_date)
date_label.config(text=f"Selected Date: {selected_date}")
# Create the main window
root = tk.Tk()
root.title("Calendar Widget")
# Create the calendar widget
cal = Calendar(root, selectmode='day', year=2024, month=9, day=7)
cal.pack(pady=20)
# Button to select date
select_button = tk.Button(root, text="Select Date", command=select_date)
select_button.pack(pady=10)
# Label to display the selected date
date_label = tk.Label(root, text="")
date_label.pack(pady=10)
# try:
# db_file_path = sys.argv[1] if len(sys.argv) > 1 else None
# print(db_file_path) if db_file_path else sys.exit("No database path provided. Exiting...")
# except SystemExit as e:
# print(e)
# sys.exit(1)
# Check if the database path was passed as an argument
if len(sys.argv) > 1:
db_file_path = sys.argv[1]
print(db_file_path)
else:
print("No database path provided. Exiting...")
sys.exit(1)
# Create main application window
root = tk.Tk()
root.title("Athletes Table")
root.geometry("1200x600")
# Create Treeview widget
columns = ("Last Name", "First Name", "MI", "Gender", "DOB", "Team ID", "Team Name", "Bib Number", "Membership Number")
tree = ttk.Treeview(root, columns=columns, show="headings", height=10)
# Configure columns
for col in columns:
tree.heading(col, text=col)
tree.column(col, width=120, anchor="center")
tree.pack(pady=10, fill="both", expand=True)
# Add Scrollbars
vsb = ttk.Scrollbar(root, orient="vertical", command=tree.yview)
vsb.pack(side="right", fill="y")
tree.configure(yscrollcommand=vsb.set)
# Bind Treeview selection
tree.bind("<<TreeviewSelect>>", select_athlete)
# Input fields for adding/modifying an athlete
frame = tk.Frame(root)
frame.pack(pady=10)
tk.Label(frame, text="Last Name:").grid(row=0, column=0)
entry_last_name = tk.Entry(frame)
entry_last_name.grid(row=0, column=1)
tk.Label(frame, text="First Name:").grid(row=0, column=2)
entry_first_name = tk.Entry(frame)
entry_first_name.grid(row=0, column=3)
tk.Label(frame, text="MI:").grid(row=0, column=5)
entry_mi = tk.Entry(frame)
entry_mi.grid(row=0, column=6)
tk.Label(frame, text="Gender:").grid(row=1, column=0)
entry_gender = tk.Entry(frame)
entry_gender.grid(row=1, column=1)
# Load the calendar icon image
calendar_icon = tk.PhotoImage(file="images/file.png")
tk.Label(frame, text="DOB:").grid(row=1, column=2)
entry_dob = tk.Entry(frame)
entry_dob.grid(row=1, column=3)
# Add the button with a calendar icon next to the DOB entry
btn_calendar = tk.Button(frame, image=calendar_icon, command=open_calendar_popup)
btn_calendar.grid(row=1, column=4, padx=5)
tk.Label(frame, text="Team ID:").grid(row=1, column=5)
entry_team_id = tk.Entry(frame)
entry_team_id.grid(row=1, column=6)
tk.Label(frame, text="Team Name:").grid(row=2, column=0)
entry_team_name = tk.Entry(frame)
entry_team_name.grid(row=2, column=1)
tk.Label(frame, text="Bib Number:").grid(row=2, column=2)
entry_bib_number = tk.Entry(frame)
entry_bib_number.grid(row=2, column=3)
tk.Label(frame, text="Membership Number:").grid(row=2, column=5)
entry_membership_number = tk.Entry(frame)
entry_membership_number.grid(row=2, column=6)
# Action buttons
button_frame = tk.Frame(root)
button_frame.pack(pady=20)
btn_add = tk.Button(button_frame, text="Add Athlete", command=add_athlete)
btn_add.grid(row=0, column=0, padx=10)
btn_update = tk.Button(button_frame, text="Update Athlete", command=update_athlete)
btn_update.grid(row=0, column=1, padx=10)
btn_delete = tk.Button(button_frame, text="Delete Athlete", command=delete_athlete)
btn_delete.grid(row=0, column=2, padx=10)
btn_clear = tk.Button(button_frame, text="Clear Fields", command=clear_inputs)
btn_clear.grid(row=0, column=3, padx=10)
# Load initial data into the Treeview
load_athletes_data(db_file_path)
root.mainloop()
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['meet_systems_main.py'],
pathex=[], # Add any additional paths here if needed
binaries=[],
datas=[
('images/britanie.png', 'images'),
('images/file.png', 'images'),
('athletes.py', '.') # Ensure athletes.py is included in the build
],
hiddenimports=['tkinter', 'PIL', 'sqlite3', 'tkcalendar'], # Include all hidden imports
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='meet_systems_main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True, # Change to False if you don’t want a console window
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='meet_systems_main'
)
enter image description here
1