solutions.py
from __future__ import print_function
import tkinter as tk
from tkinter import ttk
list_emoji = ['😀','😄','😉','😍','😐','😴','🦊','🦝','🐹','🐾','🐕','🦥','🦨','🐘','🦔','🐿','🦎','🐊','🦖','🦈','🐬','🦅',
'🦢','🦉','🦇','🕷','🎄','🎁','🎞','🖼','🎨','🛒','🏆','🎮','🕹','♟','🔈','🔔','🎵','🎤','🎧','🎹','🔒','🔑','🛠',
'🔧','⚙','🧱','💊','🔭','🧰','🛡','🏹','🗡','⚔','💣','☎','📞','📱','💻','🖥','🖨','⌨','🖱','💾','📀','🎬','📷',
'📸','📹','🔍','💡','🔦','📕','📖','📗','📚','💰','💷','📦','✏','🖊','🖌','📝','💼','📁','📅','📆','📈','📉','📊',
'📋','📏','⌛','⏳','⌚','⏰','⏱','🍕','🍟','🥪','🌮','🍦','🍩','🎂','🍰','🍫','🍬','🍭','🍽','🥝','🍓','🍏','🍄',
'🌸','🌻','🌼','🌲','🌳','🌴','🌵','🍀','🍁','🚗','🚀','⛵','🌍','🌎','🗺','🧭','⛰','🏕','🏞','🏜','🏝','🏡','⛺',
'🌄','🛏','🧻','🧽','⛅','🌤','🌦','🌩','🌠','🌈','⚡','🔥','🌊','💕','💤','💥','❌','⭕','❗','❓',
'➕','➖','💭','🗯','🕒','✔','✖','⬜','✅','❎','⬛','🔲','🔳']
########################################################################################################################
####################################### W I N D O W S H I G H D P I ########################################
########################################################################################################################
try:
from ctypes import windll
windll.shcore.SetProcessDpiAwareness(1)
except:
pass
########################################################################################################################
########################################################################################################################
################################ #################################
################################ S Q L I T E D A T A B A S E F U N C T I O N S #################################
################################ #################################
########################################################################################################################
########################################################################################################################
import sqlite3
class Database:
def create_databases(self):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
cursor.execute(
"CREATE TABLE IF NOT EXISTS animals("
"animal_id integer primary key, "
"animal_name text, "
"animal_notes text, "
"animal_state integer, "
"animal_option text)")
connection.commit()
connection.close()
def animals_add(self, a_id, a_name, a_notes, a_state, a_option):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
try:
cursor.execute("INSERT INTO animals VALUES(?, ?, ?, ?, ?)",
(a_id, a_name, a_notes, a_state, a_option))
connection.commit()
except:
print('Database error')
connection.close()
def animals_update(self, a_id, a_name, a_notes, a_state, a_option):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
cursor.execute(f'UPDATE animals SET animal_name=? WHERE animal_id={a_id}', (a_name,))
cursor.execute(f'UPDATE animals SET animal_notes=? WHERE animal_id={a_id}', (a_notes,))
cursor.execute(f'UPDATE animals SET animal_state=? WHERE animal_id={a_id}', (a_state,))
cursor.execute(f'UPDATE animals SET animal_option=? WHERE animal_id={a_id}', (a_option,))
connection.commit()
connection.close()
def animals_delete(self, a_id):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
cursor.execute(f'DELETE FROM animals WHERE animal_id={a_id}')
connection.commit()
connection.close()
def animals_select_all(self):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
cursor.execute("SELECT * FROM animals ORDER BY animal_name")
all_animals = [[row[0], row[1], row[2], row[3], row[4]] for row in cursor.fetchall()]
connection.close()
return all_animals
def animals_select_by_id(self, a_id):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
cursor.execute("SELECT * FROM animals WHERE animal_id=? ORDER BY animal_name DESC",
(a_id,)) # I can select multiple entries using WHERE, for example all the same names
animal = [[row[0], row[1], row[2], row[3], row[4]] for row in cursor.fetchall()]
# I can also format the data as Dictionary
animal_dictionary = [{'id': row[0], 'name': row[1], 'notes': row[2], 'state': row[3], 'option': row[4]} for row in cursor.fetchall()]
connection.close()
return animal
def animals_select_all_of_type(self):
connection = sqlite3.connect("./assets/solutions/sample_data.db")
cursor = connection.cursor()
cursor.execute(
"SELECT animal_name, animal_notes FROM animals ORDER BY animal_name ASC LIMIT 1") # LIMIT 1 will return only one entry
animal = [[row[0], row[1], row[2], row[3], row[4]] for row in cursor.fetchall()]
connection.close()
return animal
'''
GROUP BY
select movie_type, AVG(rating) FROM movies GROUP BY movie_type
this query will create groups of movie types containing all movies inside, and calculate the average rating for each group
'''
########################################################################################################################
########################################################################################################################
##################################################### ######################################################
##################################################### A P I ######################################################
##################################################### ######################################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
########################### G O O G L E C A L E N D A R A P I - S E T U P ############################
########################################################################################################################
'''
TERMINAL:
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
WEBSITE:
✔ Go to https://developers.google.com/calendar/quickstart/python and log in
✔ Click on "Enable the Google Calendar API"
✔ Name the and agree to terms -> Select "Desktop App" and click on "Create"
✔ Click on "Download Client Configuration", .json file
PROJECT FOLDER:
✔ Copy the downloaded .json file to my project folder
✔ Create new python file: quickstart.py and copy code from https://developers.google.com/calendar/quickstart/python
✔ Run the quickstart.py file and follow the log in procedure
✔ At this point I can only view my calendars
✔ In the quickstart.py file edit this line: SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
✔ replacing it with: SCOPES = ['https://www.googleapis.com/auth/calendar']
✔ delete the newly created pickle token.pickle file
✔ After the new login procedure I will be able to see, edit, share and delete calendars
✔ Paste and edit the following code to my app
✔ Add this import to the top of my file: from __future__ import print_function
'''
########################################################################################################################
################### G O O G L E C A L E N D A R A P I - P R I N T E V E N T S #####################
########################################################################################################################
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ['https://www.googleapis.com/auth/calendar']
def google_calendar_print():
cscroll()
creds = None
if os.path.exists('./assets/solutions/token.pickle'):
with open('./assets/solutions/token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('./assets/solutions/credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('./assets/solutions/token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('calendar', 'v3', credentials=creds)
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
statusbar.set('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now, maxResults=10, singleEvents=True, orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
statusbar.set('No upcoming events found.')
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
tk.Label(scroll, text=f"{start}, {event['summary']}").pack()
########################################################################################################################
##################### G O O G L E A P I C A L E N D A R - A D D E V E N T S #######################
########################################################################################################################
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ['https://www.googleapis.com/auth/calendar']
def google_calendar_add():
def add_event():
if check_input_date(calendar_entry.get()) and check_input_time(time_entry.get()):
user_time = f"{calendar_entry.get()} {time_entry.get()}:00"
user_time_as_date = datetime.datetime.strptime(user_time, '%Y-%m-%d %H:%M:%S')
calculated_time_as_date = user_time_as_date + relativedelta(hours=1)
title = 'Google Calendar API'
event_data = 'Google Calendar API - Add Events'
event_date = calendar_entry.get()
event_time = time_entry.get()
event_time_end = f"{str(calculated_time_as_date)[:10]}T{str(calculated_time_as_date)[11:]}"
creds = None
print(f"{title}\n{event_data}\n{event_date}\n{event_time}\n{event_time_end}\n\n")
if os.path.exists('./assets/solutions/google_api_calendar/token.pickle'):
with open('./assets/solutions/google_api_calendar/token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('./assets/solutions/google_api_calendar/credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('./assets/solutions/google_api_calendar/token.pickle', 'wb') as token:
pickle.dump(creds, token)
event = {
'summary': f'{title}',
'location': '',
'description': f'{event_data}',
'start': {
'dateTime': f'{event_date}T{event_time}:00',
'timeZone': 'Europe/London',
},
'end': {
'dateTime': f'{event_time_end}',
'timeZone': 'Europe/London',
},
'reminders': {
'useDefault': False,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10},
],
},
}
service = build('calendar', 'v3', credentials=creds)
event = service.events().insert(calendarId='primary', body=event).execute()
calendar_frame.destroy()
statusbar.set('Event added successfully')
else:
date_statusbar.set('Invalid format')
cscroll()
calendar_frame = tk.Toplevel()
calendar_frame.title("Calendar")
calendar_frame.resizable(False, False)
calendar_frame.configure(background='white')
calendar_frame.rowconfigure(0, weight=1)
date_statusbar = tk.StringVar()
date_statusbar.set('')
tk.Label(calendar_frame, text='Enter event date:', anchor='center', background='white').grid(row=1, column=0, sticky="W", pady=5)
calendar_entry = ttk.Entry(calendar_frame, width=10)
calendar_entry.grid(row=1, column=1, sticky="W", padx=10, pady=(0, 10))
calendar_entry.focus()
calendar_entry.bind("<Return>", lambda event: add_event())
calendar_entry.bind("<Escape>", lambda event: calendar_frame.destroy())
calendar_entry.insert(0, datetime.date.today())
tk.Label(calendar_frame, text='Enter start hour:', anchor='center', background='white').grid(row=2, column=0, sticky="W", pady=5)
time_entry = ttk.Entry(calendar_frame, width=10)
time_entry.grid(row=2, column=1, sticky="W", padx=10, pady=(0, 10))
time_entry.bind("<Return>", lambda event: add_event())
time_entry.bind("<Escape>", lambda event: calendar_frame.destroy())
time_entry.insert(0, str(datetime.datetime.now())[11:16])
button_frame = tk.Frame(calendar_frame, bg='white')
button_frame.grid(row=3, column=0, columnspan=2, sticky="EW")
button_frame.columnconfigure(0, weight=1)
tk.Button(button_frame, text='Send', font=("Georgia", 7), bg='white', relief='flat', command=add_event).grid(row=0, column=1, sticky="W")
tk.Button(button_frame, text='Cancel', font=("Georgia", 7), bg='white', relief='flat', command=lambda: calendar_frame.destroy()).grid(row=0, column=2, sticky="W")
tk.Label(calendar_frame, textvariable=date_statusbar, background='grey50', foreground='white').grid(row=4, column=0, columnspan=2, sticky="EW")
########################################################################################################################
############################## G O O G L E A P I D R I V E - S E T U P ###############################
########################################################################################################################
'''
TERMINAL:
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
WEBSITE:
✔ Go to https://developers.google.com/drive/api/v3/quickstart/python and log in
✔ Click on "Enable the Google Drive API"
✔ Name the and agree to terms -> Select "Desktop App" and click on "Create"
✔ Click on "Download Client Configuration", .json file
PROJECT FOLDER:
✔ Copy the downloaded .json file to my project folder
✔ Create a new function and code from https://developers.google.com/drive/api/v3/quickstart/python
✔ Run the function file and follow the log in procedure
✔ Edit SCOPES and change it to: SCOPES = ['https://www.googleapis.com/auth/drive']
✔ Delete the newly created pickle token.pickle file
✔ Add this import to the top of my file: from __future__ import print_function'''
########################################################################################################################
################ G O O G L E A P I D R I V E - C R E A T E S P R E A D S H E E T ##################
########################################################################################################################
def google_drive_add():
'''IMPORTANT: Each Google API Pickle and Credentials file should have it's own Folder
Check paths'''
SCOPES = ['https://www.googleapis.com/auth/drive']
from googleapiclient import discovery
creds = None
if os.path.exists('./assets/solutions/google_api_drive/token.pickle'):
with open('./assets/solutions/google_api_drive/token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'./assets/solutions/google_api_drive/credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('./assets/solutions/google_api_drive/token.pickle', 'wb') as token:
pickle.dump(creds, token)
try:
# CREATE SPREADSHEET
service = discovery.build('sheets', 'v4', credentials=creds)
my_title = 'Solutions'
spreadsheet = {
'properties': {'title': my_title},
}
spreadsheet = service.spreadsheets().create(body=spreadsheet, fields='spreadsheetId').execute()
# print('Spreadsheet ID: {0}'.format(spreadsheet.get('spreadsheetId')))
my_spreadsheet_id = spreadsheet.get('spreadsheetId')
# print(my_spreadsheet_id)
range_name = 'Sheet1'
# Data
formatted_list = [SAMPLE_LIST]
body = {'values': formatted_list}
result = service.spreadsheets().values().append(
spreadsheetId=my_spreadsheet_id, range=range_name,
valueInputOption='RAW', body=body).execute()
# statusbar.set('{0} cells appended.'.format(result.get('updates').get('updatedCells')))
statusbar.set("Google Drive Spreadsheet created")
except:
statusbar.set("Error")
########################################################################################################################
############################ W E A T H E R - O P E N W E A T H E R A P I #############################
########################################################################################################################
# https://openweathermap.org/current
import requests
import json
from PIL import ImageTk, Image
from io import BytesIO
def weather_api():
def get_api(town):
try:
api_request = requests.get(f"http://api.openweathermap.org/data/2.5/weather?id={town}&appid={api_id}")
api = json.loads(api_request.content)
except Exception as e:
statusbar.set("Error")
return api
def create_labels(i, each_place):
image_url = f"https://openweathermap.org/img/w/{get_api(each_place)['weather'][0]['icon']}.png"
response = requests.get(image_url)
icon_image = ImageTk.PhotoImage(Image.open(BytesIO(response.content)))
image_label = tk.Label(scroll, image=icon_image)
image_label.grid(row=i, column=0, padx=10, pady=0)
image_label.image = icon_image
tk.Label(scroll, text=get_api(each_place)['name'], font=("Calibri", 10)).grid(row=i, column=1, padx=10, pady=0)
tk.Label(scroll, text=f"{round(((get_api(each_place)['main']['temp']) - 273.15), 2)}\u00B0C", font=("Calibri", 10)).grid(row=i, column=2, padx=10, pady=0)
tk.Label(scroll, text=(get_api(each_place)['weather'][0]['description']).title(), font=("Calibri", 10)).grid(row=i, column=3, padx=10, pady=0)
cscroll()
places = ['2657839', '2656565', '2651753', '2646630', '2646384']
api_id = 'your_api_here'
try:
for i, each_place in enumerate(places):
create_labels(i, each_place)
except:
statusbar.set("Error")
########################################################################################################################
########################################################################################################################
################################## #################################
################################## A R T I F I C I A L I N T E L L I G E N C E #################################
################################## #################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
###################################### S P E E C H R E C O G N I T I O N ######################################
########################################################################################################################
'''
pip install SpeechRecognition
pip install pyaudio
or: go to https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio and download appropriate pyaudio module
or: pip install pipwin
pipwin install pyaudio'''
from tkinter import messagebox
import speech_recognition as sr
try:
recognizer = sr.Recognizer()
microphone = sr.Microphone()
except:
pass
def ai_speech_recognition():
try:
with microphone as source:
recognizer.adjust_for_ambient_noise(source)
audio = recognizer.listen(source)
try:
response = recognizer.recognize_google(audio)
statusbar.set(f"{response.capitalize()}")
except:
messagebox.showinfo(title='Error', message='There was a problem recording your message, please try again')
except:
statusbar.set('No microphone detected')
########################################################################################################################
########################################################################################################################
################################################### ###################################################
################################################### C L A S S E S ###################################################
################################################### ###################################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
#################################### B U T T O N W I T H P I C T U R E #####################################
########################################################################################################################
class MyButton(tk.Button):
pictures_path = "./assets/solutions/"
def __init__(self, container, pic='', pic_px=0, *args, **kwargs):
super().__init__(container, *args, **kwargs)
self.pic = pic
self.px = pic_px
self.im = Image.open(self.pictures_path + self.pic)
self.im.thumbnail((pic_px, pic_px))
self.pic = ImageTk.PhotoImage(self.im)
self.config(background='white',
activebackground='white',
image=self.pic,
compound="top",
relief="flat",
width=pic_px,
borderwidth=0,
font=("Calibri", 9))
self.grid(padx=15, pady=15)
def class_button():
cscroll()
MyButton(scroll,
text='PictureButton',
pic="pic01.png",
pic_px=100,
command=lambda: statusbar.set('Button')).grid(row=0, column=0)
########################################################################################################################
######################## D I S P L A Y A T T R I B U T E S O F A W I D G E T #########################
########################################################################################################################
class Attributes(tk.Toplevel):
def __init__(self, container, widget, *args, **kwargs):
super().__init__(container, *args, **kwargs)
self.geometry("1000x1000")
self.focus()
print(widget)
tk.Label(self, text=f"Widget: {widget}", font=("Calibri", 24)).pack()
tree_scroll = ttk.Scrollbar(self)
tree_scroll.pack(side="right", fill="y")
attrb_tree = ttk.Treeview(self, yscrollcommand=tree_scroll.set)
attrb_tree.pack(fill="both", expand=True)
tree_scroll.config(command=attrb_tree.yview)
attrb_tree['columns'] = ('Attribute', 'Value')
attrb_tree.heading("Attribute", text="Attribute", anchor="center")
attrb_tree.heading("Value", text="Value", anchor="center")
attrb_tree.column("#0", width=0, stretch="no")
attrb_tree.column("Attribute", anchor="w", width=250)
attrb_tree.column("Value", anchor="w", width=350)
try:
attrb_tree.insert(parent='', index='end', iid=0, text="", values=('WIDGET', f'{widget.widgetName}'.upper()))
except AttributeError:
pass
for i, each_key in enumerate(widget.keys(), start=1):
attrb_tree.insert(parent='', index='end', iid=i, text="", values=(each_key, widget[f'{each_key}']))
########################################################################################################################
########################################### T K I N T E R F R A M E ###########################################
########################################################################################################################
class MyFrame(tk.Frame):
def __init__(self, container, *args, **kwargs): # container is root
super().__init__(container, *args, **kwargs)
self.columnconfigure(0, minsize=500, weight=1)
self.rowconfigure(0, minsize=500, weight=1)
self.config(bg="white")
def display_my_frame():
cscroll()
my_frame = MyFrame(scroll)
my_frame.pack()
tk.Label(my_frame, text="This label is inside MyFrame Class Frame").grid(row=0, column=0)
########################################################################################################################
################################################# L I M I T E R ##################################################
########################################################################################################################
class Limiter(tk.Frame):
def __init__(self, container, data, widgets_per_window=10):
super().__init__(container)
self.data = data
self.widgets_per_window = widgets_per_window
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
root.unbind("<Delete>")
root.unbind("<Right>")
root.unbind("<Left>")
if self.data:
self.divided_data = [self.data[x:x+self.widgets_per_window] for x in range(0, len(self.data), self.widgets_per_window)]
self.chunks_number = len(self.divided_data)
self.divided_data_index = 0
self.frame_labels = tk.Frame(self, bg="#F9F7F7")
self.frame_labels.grid(row=0, column=0, sticky="NEWS")
self.frame_labels.columnconfigure(0, weight=1)
if len(self.data) > self.widgets_per_window:
root.bind("<Delete>", lambda event: self.reset_screen())
root.bind("<Button-2>", lambda event: self.reset_screen())
self.frame_buttons = tk.Frame(self, bg="#F9F7F7")
self.frame_buttons.grid(row=1, column=0, sticky="EW")
self.frame_buttons.columnconfigure((0, 4), weight=1)
self.button_previous = tk.Button(self.frame_buttons, text="Previous", state="disabled", command=lambda: self.previous_screen(), width=20, bg="#3C4048", fg="#F9F7F7", relief="flat")
self.button_previous.grid(row=0, column=0, sticky="E")
self.button_reset = tk.Button(self.frame_buttons, text=f"Reset", command=lambda: self.reset_screen(), width=20, bg="#3C4048", fg="#F9F7F7", relief="flat")
self.button_reset.grid(row=0, column=1, padx=2)
self.button_next = tk.Button(self.frame_buttons, text="Next", command=lambda: self.next_screen(), width=20, bg="#3C4048", fg="#F9F7F7", relief="flat")
self.button_next.grid(row=0, column=2, sticky="W")
root.bind("<Right>", lambda event: self.next_screen())
root.bind("<MouseWheel>", lambda event: self.mouse_scroll(event, "right"))
self.button_reset["text"] = f"Page {self.divided_data_index + 1} / {self.chunks_number} | {len(self.data)}"
self.prepare_widgets(self.divided_data_index)
def mouse_scroll(self, event, allowed_direction):
if allowed_direction == 'both':
if event.delta < 0:
self.next_screen()
else:
self.previous_screen()
if allowed_direction == 'right':
if self.divided_data_index < self.chunks_number-1:
if event.delta < 0:
self.next_screen()
else:
if self.divided_data_index > 0:
if event.delta > 0:
self.previous_screen()
def next_screen(self):
self.button_previous["state"] = 'normal'
root.bind("<Left>", lambda event: self.previous_screen())
root.bind("<MouseWheel>", lambda event: self.mouse_scroll(event, "both"))
self.divided_data_index += 1
self.prepare_widgets(self.divided_data_index)
if self.divided_data_index == self.chunks_number-1:
self.button_next["state"] = 'disabled'
root.unbind("<Right>")
root.bind("<MouseWheel>", lambda event: self.mouse_scroll(event, "left"))
def previous_screen(self):
self.button_next["state"] = 'normal'
root.bind("<Right>", lambda event: self.next_screen())
root.bind("<MouseWheel>", lambda event: self.mouse_scroll(event, "both"))
self.divided_data_index -= 1
self.prepare_widgets(self.divided_data_index)
if self.divided_data_index == 0:
self.button_previous["state"] = "disabled"
root.unbind("<Left>")
root.bind("<MouseWheel>", lambda event: self.mouse_scroll(event, "right"))
def reset_screen(self):
self.divided_data_index = 0
self.button_next["state"] = 'normal'
root.bind("<Right>", lambda event: self.next_screen())
root.bind("<MouseWheel>", lambda event: self.mouse_scroll(event, "right"))
self.button_previous["state"] = "disabled"
root.unbind("<Left>")
self.prepare_widgets(self.divided_data_index)
def prepare_widgets(self, main_index):
for child in self.frame_labels.winfo_children():
child.destroy()
if self.data:
self.button_reset["text"] = f"Page {self.divided_data_index + 1} / {self.chunks_number} | {len(self.data)}"
for index, d in enumerate(self.divided_data[main_index]):
self.create_widgets(index, d)
def create_widgets(self, index, dt):
tk.Label(self.frame_labels, bg="#F9F7F7", fg="#3C4048", text=f"Label {dt}").grid(row=index, column=0)
def display_limiter():
cscroll()
dt = ['I am first 😆']
for i in range(1, 25):
dt.append(i)
dt.append('I am last 😭')
Limiter(root, data=dt, widgets_per_window=10).grid(row=0, column=0, sticky='NEWS')
########################################################################################################################
########################################################################################################################
#################################### ####################################
#################################### C H A R T S A N D S T A T I S T I C S ####################################
#################################### ####################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
############################################### P I E C H A R T ###############################################
########################################################################################################################
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def doughnut_chart():
chart_window = tk.Toplevel()
chart_window.title('Chart')
plt.rcParams['font.size'] = 9
plt.rcParams.update({'figure.autolayout': True})
chart_values = [80, 95, 85]
chart_labels = ['Nikon D3400', 'Nikon D7500', 'Samsung S20']
chart_explode = [0, 0.1, 0]
chart_colours = ['lightblue', 'lightgreen', 'blue', 'orange']
my_chart = plt.Figure(figsize=(5, 5), dpi=100)
my_chart_subplot = my_chart.add_subplot(111)
my_chart_subplot.pie(chart_values,
labels=chart_labels,
explode=chart_explode,
colors=chart_colours,
rotatelabels=False,
labeldistance=1.1,
pctdistance=0.85,
autopct='%1.1f%%',
shadow=False,
startangle=90)
my_chart_subplot.axis('equal')
my_chart_subplot.set_title('Cameras')
my_chart_circle = plt.Circle((0, 0), 0.7, color='white')
my_chart.gca().add_artist(my_chart_circle)
my_chart_pie = FigureCanvasTkAgg(my_chart, chart_window)
my_chart_pie.get_tk_widget().grid(row=0, column=0, sticky="NEWS")
########################################################################################################################
############################################ S I M P L E G R A P H ############################################
########################################################################################################################
def simple_graph():
import numpy as np
house_prices = np.random.normal(200000, 25000, 5000)
plt.hist(house_prices, 10)
plt.show()
########################################################################################################################
########################################################################################################################
################################################### ####################################################
################################################### E M A I L ####################################################
################################################### ####################################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
########################################### E M A I L S I M P L E #############################################
########################################################################################################################
import smtplib
from email.message import EmailMessage
def email_simple():
email_content = 'Email Content'
email = EmailMessage()
email['from'] = 'New Message'
email['to'] = 'lord.huriko@gmail.com'
email['subject'] = "New message"
email.set_content(email_content)
with smtplib.SMTP(host='smtp.gmail.com', port=587) as smtp:
smtp.ehlo()
smtp.starttls()
smtp.login('photoituk@gmail.com', 'ulrzfqnmxdwjgbxm')
smtp.send_message(email)
statusbar.set('Email sent')
########################################################################################################################
######################################### E M A I L A D V A N C E D ###########################################
########################################################################################################################
import smtplib
from email.message import EmailMessage
import re
def email_advanced():
def check_email(email_address):
email_str = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'
return re.search(email_str, email_address)
def send_now():
if check_email(email_entry.get()):
email_content = 'Email Content'
email = EmailMessage()
email['from'] = 'App'
email['to'] = email_entry.get()
email['subject'] = "Text from App"
email.set_content(email_content)
with smtplib.SMTP(host='smtp.gmail.com', port=587) as smtp:
smtp.ehlo()
smtp.starttls()
smtp.login('photoituk@gmail.com', 'ulrzfqnmxdwjgbxm')
smtp.send_message(email)
statusbar.set('Email sent')
email_frame.destroy()
else:
statusbar.set('Invalid email address')
email_frame = tk.Toplevel()
email_frame.title("Send Email")
email_frame.columnconfigure(0, weight=1)
email_frame.rowconfigure(2, weight=1)
ttk.Label(email_frame, text='Your email', anchor='center').grid(row=1, column=0, columnspan=3, sticky="EW", pady=5)
email_entry = ttk.Entry(email_frame)
email_entry.grid(row=2, column=0, columnspan=3, sticky="EW", padx=10, pady=(0, 10))
email_entry.focus()
email_entry.bind("<Return>", lambda event: send_now())
ttk.Button(email_frame, text='Send', command=lambda: send_now()).grid(row=3, column=1, sticky="W")
ttk.Button(email_frame, text='Cancel', command=lambda: email_frame.destroy()).grid(row=3, column=2, sticky="W")
########################################################################################################################
########################################################################################################################
######################################## ########################################
######################################## E X P O R T F U N C T I O N S ########################################
######################################## ########################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
######################################### E X P O R T D A T A B A S E #########################################
########################################################################################################################
import shutil
def backup_database():
path = filedialog.askdirectory(title='Select folder')
shutil.copyfile("./assets/solutions/DATA_SAMPLE.DAT", f'{path}/DATA_SAMPLE.DAT')
statusbar.set('Backup complete')
########################################################################################################################
#################################### E X P O R T F I L E A S C S V ######################################
########################################################################################################################
def export_csv():
header_text = 'ITEM\tDESCRIPTION\t\n'
list_text = ['Break', 'This\ttext\nwould normally; break the: CSV, import'],\
['Better', 'This text is OK and will be imported without errors.']
# Remove all characters which may break the CSV import
message_text = ''
for each_text in list_text:
text_to_clear = str(each_text[1])
text_to_clear = text_to_clear.replace(",", "")
text_to_clear = text_to_clear.replace("\n", " ")
text_to_clear = text_to_clear.replace("\t", " ")
text_to_clear = text_to_clear.replace(";", " ")
message_text += f'{each_text[0]}\t{text_to_clear}\t\n'
data_to_export = header_text + message_text
try:
file_path = filedialog.asksaveasfilename(title="Save File",
defaultextension="csv",
filetypes=(("CSV files", "*.csv"), ("all files", "*.*")))
with open(file_path, "w", encoding="utf-8") as file:
file.write(data_to_export)
statusbar.set('All messages exported.')
except (AttributeError, FileNotFoundError):
statusbar.set("Export cancelled.")
return
########################################################################################################################
################################### E X P O R T F I L E A S P D F #######################################
########################################################################################################################
from fpdf import FPDF
import os
def create_pdf():
if not os.path.exists('./assets/solutions/PDF'):
os.makedirs('./assets/solutions/PDF')
document_name = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
pdf = FPDF(format="A4")
pdf.set_font("arial", '', 8)
pdf.add_page()
list_for_pdf = ['Fox', 'Cat', 'Dog', 'Dolphin', 'Owl', 'Heron', 'Red Deer', 'Mountain Hare', 'Ptarmigan', 'Robin']
for each_item in list_for_pdf:
pdf.image('./assets/solutions/pic01.png', None, None, w=20, h=20)
pdf.ln(1)
pdf.cell(10, 5, str(each_item))
pdf.ln(5)
pdf_path = f'.\\assets\\solutions\\PDF\\'
pdf.output(f'{pdf_path}{document_name}.pdf', 'F')
statusbar.set('PDF created')
os.startfile(pdf_path)
########################################################################################################################
#################################### E X P O R T F I L E A S T X T ######################################
########################################################################################################################
from tkinter import filedialog
def export_txt():
data_to_print = 'Squirrels are awesome'
try:
file_path = filedialog.asksaveasfilename(title='Save File',
defaultextension="txt",
filetypes=(("TXT files", "*.txt"), ("all files", "*.*")))
with open(file_path, "w") as file:
file.write(data_to_print)
statusbar.set('Timesheet exported')
except (AttributeError, FileNotFoundError):
statusbar.set("Save operation cancelled")
return
########################################################################################################################
############################ P R I N T W I T H D E F A U L T P R I N T E R ##############################
########################################################################################################################
import os
import tempfile
def printer_print():
try:
# This option doesn't work with UTF characters, like 🏕 ☀
temporary_file = tempfile.mktemp(".txt")
open(temporary_file, "w").write(SAMPLE_LIST[0])
os.startfile(temporary_file, 'print')
except:
# So this option will run if UTF characters used
with open("./assets/solutions/temp.txt", "w", encoding="utf-8") as file:
file.write(SAMPLE_LIST[0])
os.startfile(".\\assets\\solutions\\temp.txt", 'print')
########################################################################################################################
########################################################################################################################
###################################### #######################################
###################################### F I L E S A N D F O L D E R S #######################################
###################################### #######################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
################################# C R E A T E A N D O P E N F O L D E R #################################
########################################################################################################################
import os
def create_and_open_folder():
if not os.path.exists('./assets/solutions/FOLDER_NAME'):
os.makedirs('./assets/solutions/FOLDER_NAME')
os.startfile('.\\assets\\solutions\\FOLDER_NAME')
########################################################################################################################
############### C R E A T E F O L D E R S W I T H U N I Q U E Y-M-D-H-M-S N A M E S ###############
########################################################################################################################
import datetime
from pathlib import Path
import os
def create_timestamp_folder():
folder_name = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
path = f'.\\assets\\solutions\\{folder_name}'
Path(path).mkdir(parents=True, exist_ok=True)
os.startfile(f'.\\assets\\solutions\\{folder_name}')
########################################################################################################################
################################## D I S P L A Y A B S O L U T E P A T H ###################################
########################################################################################################################
import os
def absolute_path():
cscroll()
file_path = filedialog.askopenfilename()
absolute_folder_path = os.path.abspath(file_path)
statusbar.set(absolute_folder_path)
########################################################################################################################
######################### D I S P L A Y A L L F I L E S I N A F O L D E R #########################
########################################################################################################################
def display_all_files():
cscroll()
for i, each_item in enumerate(glob('assets/*')):
create_labels(i, each_item)
########################################################################################################################
###################################### D I S P L A Y F I L E N A M E #######################################
########################################################################################################################
import os
def display_file_name():
cscroll()
file_path = filedialog.askopenfilename()
file_name = os.path.basename(file_path)
statusbar.set(file_name)
########################################################################################################################
######################### D I S P L A Y F I R S T P N G I N A F O L D E R #########################
########################################################################################################################
from glob import glob
def select_first_png():
cscroll()
selected_png = str(glob(f'assets/*.PNG')[0])
statusbar.set(selected_png)
########################################################################################################################
################################### O P E N E X T E R N A L P R O G R A M ##################################
########################################################################################################################
def open_app():
import os
cscroll()
tk.Button(scroll,
text="Open program",
command=lambda: os.system('"%s"' % filedialog.askopenfilename())).pack()
'''
'"%s"' % - This expression is here in case there are spaces in the path.
This allows Tkinter to read the spaces as part of path and not split the string.
'''
########################################################################################################################
############################################### O P E N F I L E ###############################################
########################################################################################################################
from tkinter import filedialog
def open_file():
filename = filedialog.askopenfilename(initialdir='/assets',
title="Select a file",
filetypes=(("PNG FIles", "*.png"), ("All files", "*.*")))
statusbar.set(filename)
########################################################################################################################
########################################################################################################################
################################################## ###################################################
################################################## I M A G E S ###################################################
################################################## ###################################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
########################################## A N I M A T E I M A G E ############################################
########################################################################################################################
def animate_image():
cscroll()
happy = tk.PhotoImage(file="./assets/solutions/face_happy.png")
crazy = tk.PhotoImage(file="./assets/solutions/face_crazy.png")
image_label = tk.Label(scroll, bg='white', image=happy)
image_label.image = happy
image_label.pack(padx=20, pady=20)
image_label.bind("<Enter>", lambda x: image_label.configure(image=crazy))
image_label.bind("<Leave>", lambda x: image_label.configure(image=happy))
########################################################################################################################
########################################## D I S P L A Y I M A G E ############################################
########################################################################################################################
from PIL import Image, ImageTk
'''I should always define images outside of functions, it is simpler this way:
my_img = ImageTk.PhotoImage(Image.open('pic.jpg'))
tk.Label(image=my_img).pack()
Important: I cannot create image like this inside a function, just a python error. To make it work, first I have to
define the my_img as global variable within the function: global my_img, and then the rest. This way it will work.
To create image indide a function I have to write this code:
'''
def display_image():
image_original = Image.open("./assets/solutions/pic01.png")
# image_edited = image_original.resize((100, 100), Image.ANTIALIAS)
image_final = ImageTk.PhotoImage(image_original) # or image_edited
cscroll()
label_with_images = ttk.Label(scroll, image=image_final, anchor="nw")
label_with_images.image = image_final
label_with_images.grid(row=0, column=0, sticky="NEWS")
########################################################################################################################
################################## D I S P L A Y I M A G E S I M P L E #####################################
########################################################################################################################
def display_image_simple():
# Remember that image has to be created outside a function
# Also image has to be assigned twice
cscroll()
my_image = tk.PhotoImage(file="./assets/solutions/picture.png")
label_image = ttk.Label(scroll, image=my_image, anchor="nw")
label_image.image = my_image
label_image.grid(row=0, column=0, sticky="NEWS", padx=200, pady=50)
########################################################################################################################
############### D I S P L A Y A N I M A G E R E S I Z E D T O F I T W I N D O W ################
########################################################################################################################
from tkinter import filedialog
from PIL import Image, ImageTk
def display_image_adjusted():
cscroll()
def set_image_size(path_to_image):
image_width = root.winfo_width()
image_height = root.winfo_height() - 50
try:
image_original = Image.open(f"{path_to_image}")
width, height = image_original.size
if height > width:
percent = (height - root.winfo_height()) * (100 / height)
new_width = int((width / 100 * (100 - percent)))
image_edited = image_original.resize((new_width, image_height), Image.ANTIALIAS)
image_final = ImageTk.PhotoImage(image_edited)
else:
percent = (width - root.winfo_width()) * (100 / width)
new_height = int((height / 100 * (100 - percent)))
image_edited = image_original.resize((image_width, new_height), Image.ANTIALIAS)
image_final = ImageTk.PhotoImage(image_edited)
return image_final
except (AttributeError, FileNotFoundError):
statusbar.set("Open File Cancelled")
def open_file():
file_path = filedialog.askopenfilename()
image_imported = set_image_size(file_path)
image_label = ttk.Label(scroll, image=image_imported, anchor='center')
image_label.image = image_imported
image_label.grid(row=1, column=0, sticky="NEWS")
ttk.Button(scroll, text="Open File", command=lambda: open_file()).grid(row=0, column=0, sticky="EW")
########################################################################################################################
#################################### I M A G E A S B A C K G R O U N D #####################################
########################################################################################################################
from PIL import ImageTk, Image
def image_as_background():
def change_text(new_text):
canvas.itemconfig(text_bg, text=new_text)
canvas.itemconfig(text_fg, text=new_text)
global image_canvas # Global to stop tkinter removing this image with it's garbage collector
image_canvas = ImageTk.PhotoImage(file="./assets/solutions/pic01.png")
canvas_window = tk.Toplevel(root)
canvas_window.columnconfigure(0, weight=1)
canvas_window.rowconfigure(0, weight=1)
canvas = tk.Canvas(canvas_window, width=1680, height=800, bd=0)
canvas.pack(fill="both", expand=True)
canvas.create_image(0, 0, image=image_canvas, anchor="nw")
# Create text with an outline
text_bg = canvas.create_text(200, 100, text="Hello World!", font=("Helvetica", 40), fill='white', anchor='nw')
text_fg = canvas.create_text(202, 102, text="Hello World!", font=("Helvetica", 40), fill='black', anchor='nw')
# Create buttons to update text and place them in canvas
button_1 = tk.Button(canvas_window, text="Pets", command=lambda: change_text('Exotic Pets'), width=20)
button_2 = tk.Button(canvas_window, text="Adventures", command=lambda: change_text('Amazing Adventures'), width=20)
button_1_window = canvas.create_window(10, 10, anchor="nw", window=button_1)
button_2_window = canvas.create_window(200, 10, anchor="nw", window=button_2)
# Just to show how, this is how to add other widgets to canvas
entry_box = tk.Entry(canvas_window, font=("Calibri", 14), width=20, fg='green', bd=0)
entry_box_window = canvas.create_window(500, 10, anchor='nw', window=entry_box)
########################################################################################################################
################## I M A G E A S B A C K G R O U N D W I T H A U T O R E S I Z E ##################
########################################################################################################################
from PIL import ImageTk, Image
def image_as_background_with_resize():
def resize_canvas_window(e):
global image_original, image_resized, image_canvas
image_original = Image.open("./assets/solutions/pic01.png")
image_resized = image_original.resize((e.width, e.height), Image.ANTIALIAS)
image_canvas = ImageTk.PhotoImage(image_resized)
# Add the image back to canvas
canvas.create_image(0, 0, image=image_canvas, anchor="nw")
# Text has to be reapplied
text_bg = canvas.create_text(200, 100, text="Hello World!", font=("Helvetica", 40), fill='white', anchor='nw')
global image_canvas_start # Global to stop tkinter removing this image with it's garbage collector
image_canvas_start = ImageTk.PhotoImage(file="./assets/solutions/pic01.png")
canvas_window = tk.Toplevel(root)
canvas_window.columnconfigure(0, weight=1)
canvas_window.rowconfigure(0, weight=1)
canvas_window.bind("<Configure>", resize_canvas_window)
canvas = tk.Canvas(canvas_window, width=1280, height=800, bd=0)
canvas.pack(fill="both", expand=True)
canvas.create_image(0, 0, image=image_canvas_start, anchor="nw")
# Create text with an outline
text_bg = canvas.create_text(200, 100, text="Hello World!", font=("Helvetica", 40), fill='white', anchor='nw')
########################################################################################################################
########################################################################################################################
########################################### ###########################################
########################################### P O P U P W I N D O W S ###########################################
########################################### ###########################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
################################################## D I A L O G ###################################################
########################################################################################################################
from tkinter import filedialog
####################################### A S K O P E N F I L E N A M E ######################################
def open_txt():
file_path = filedialog.askopenfilename(initialdir="./", title='Select File', filetypes=(("TXT files","*.txt"),("all files","*.*")))
try:
with open(file_path, "r") as file:
content = file.read()
cscroll()
display_file = tk.Text(scroll)
display_file.grid(row=0, column=0)
display_file.insert("1.0", content)
except (AttributeError, FileNotFoundError):
statusbar.set("Open operation cancelled")
return
###################################### A S K O P E N F I L E N A M E S #####################################
def open_many_files():
files = filedialog.askopenfilenames(title="Select Files")
cscroll()
for i, each_file in enumerate(files, 1):
tk.Label(scroll, text=f"File {i}:\t{each_file}").grid(row=i, column=0, sticky="w")
########################################## O P E N D I R E C T O R Y ##########################################
def open_directory():
path_to_directory = filedialog.askdirectory()
statusbar.set(path_to_directory)
####################################### A S K S A V E F I L E N A M E ######################################
def save_txt():
def save():
try:
file_path = filedialog.asksaveasfilename(initialdir="./", title='Save File', defaultextension="txt", filetypes=(("TXT files", "*.txt"), ("all files", "*.*")))
content = display_file.get("1.0", "end-1c")
with open(file_path, "w") as file:
file.write(content)
except (AttributeError, FileNotFoundError):
statusbar.set("Save operation cancelled")
return
cscroll()
display_file = tk.Text(scroll)
display_file.grid(row=0, column=0, sticky="NEWS")
ttk.Button(scroll, text="Save", command=save).grid(row=1, column=0, sticky="EW")
########################################################################################################################
############################################## M E S S A G E B O X ###############################################
########################################################################################################################
from tkinter import messagebox
# Icons available: error, info, question, warning
############################################# I N F O R M A T I O N ##############################################
def messagebox_showerror():
return messagebox.showerror(title='Error', message='Error')
def messagebox_showinfo():
return messagebox.showinfo(title='Info', message='Information')
def messagebox_showwarning():
return messagebox.showwarning(title='Warning', message='Warning')
################################################# C H O I C E ####################################################
def run_messagebox(function_to_call):
if function_to_call():
statusbar.set('Messagebox Confirmed')
else:
statusbar.set('Messagebox Denied')
def messagebox_askokcancel():
return messagebox.askokcancel(title='OK/Cancel', message='OK or Cancel')
def messagebox_askretrycancel():
return messagebox.askretrycancel(title='Retry/Cancel', message='Retry or Cancel')
def messagebox_askyesno():
return messagebox.askyesno(title='Yes/No', message='Yes or No', icon='question')
def messagebox_askyesnocancel():
return messagebox.askyesnocancel(title='Yes/No/Cancel', message='Yes or No or Cancel', icon='question')
########################################################################################################################
############################################ P O P U P S I M P L E ############################################
########################################################################################################################
def simple_popup_window():
popup_window = tk.Toplevel()
popup_window.geometry("350x200")
popup_window.resizable(False, False)
popup_window.title('Popup Window')
frame_top = ttk.Frame(popup_window)
frame_top.grid(row=0, column=0, sticky="EW")
frame_top.columnconfigure(0, weight=1)
ttk.Label(frame_top, text='Top Frame', anchor="center").grid(row=0, column=0, padx=10, pady=10, sticky="EW")
frame_main = ttk.Frame(popup_window)
frame_main.grid(row=1, column=0, sticky="NEWS")
frame_main.columnconfigure(0, weight=1)
ttk.Label(frame_main, text='Main Frame', anchor="center").grid(row=0, column=0, padx=10, pady=10, sticky='EW')
frame_buttons = ttk.Frame(popup_window)
frame_buttons.grid(row=2, column=0, sticky="EW")
frame_buttons.columnconfigure(0, weight=1)
popup_add_button = ttk.Button(frame_buttons, text='Add', command=lambda: statusbar.set("Add function"))
popup_add_button.grid(row=0, column=1, sticky="w")
popup_cancel_button = ttk.Button(frame_buttons, text="Cancel", command=lambda: popup_window.destroy())
popup_cancel_button.grid(row=0, column=2, sticky="w")
########################################################################################################################
####################################### R I G H T C L I C K M E N U ########################################
########################################################################################################################
def rightclick_menu():
def my_popup(event):
rightclick_menu.tk_popup(event.x_root, event.y_root)
rightclick_menu = tk.Menu(root, tearoff=False)
rightclick_menu.add_command(label="Say Hello", command=lambda: statusbar.set("Hello"))
rightclick_menu.add_command(label="Say Goodbye", command=lambda: statusbar.set("Goodbye"))
rightclick_menu.add_separator()
rightclick_menu.add_command(label="Exit", command=lambda: root.quit())
root.bind("<Button-3>", my_popup)
########################################################################################################################
########################################################################################################################
######################################## ########################################
######################################## S Y S T E M F U N C T I O N S ########################################
######################################## ########################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
################################### A U T O R E P E A T F U N C T I O N S ##################################
########################################################################################################################
add_number = 0
keep_running = True
def auto_repeat_function():
def auto_repeat():
global add_number
global keep_running
if keep_running:
statusbar.set(f"Function ran {add_number} times.")
add_number += 1
root.after(1000, auto_repeat) # Time in milliseconds, 1000 = 1 sec
def break_auto_repeat():
global keep_running
keep_running = False
cscroll()
ttk.Button(scroll, text='Start', command=lambda: auto_repeat()).pack(pady=5)
ttk.Button(scroll, text='Stop', command=lambda: break_auto_repeat()).pack(pady=5)
########################################################################################################################
############## A U T O P O P U L A T E A N D C R E A T E C L I C K A B L E L A B E L S ###############
########################################################################################################################
def autopopulate(input_list):
cscroll()
for i, each_item in enumerate(input_list):
create_labels(i, each_item)
def create_labels(i, each_item):
label = ttk.Label(scroll, text=f'New label:\t{each_item}', anchor="w", wraplength=900, justify="center", font=("calibri", 20))
label.grid(row=int(i), column=0, padx=10, pady=10, sticky="EW")
label.bind("<Enter>", lambda *args: statusbar.set(f'Mouse over Label {each_item}.'))
label.bind("<Leave>", lambda *args: statusbar.set(f'Mouse no longer over Label {each_item}.'))
label.bind("<Button-1>", lambda *args: statusbar.set(f'Label {each_item} has just been clicked.'))
########################################################################################################################
################################# B A C K U P D A T A B A S E - A U T O #################################
########################################################################################################################
def backup_database_auto():
current_date_and_time = datetime.datetime.now()
folder_name = current_date_and_time.strftime('%Y%m%d%H%M%S')
path = f'.\\assets\\solutions\\{folder_name}'
Path(path).mkdir(parents=True, exist_ok=True)
shutil.copyfile("./assets/solutions/database_data.dat", f'./assets/solutions/{folder_name}/database_data_backup.dat')
statusbar.set('Backup complete')
########################################################################################################################
############################### B A C K U P D A T A B A S E - S E L E C T ###############################
########################################################################################################################
def backup_database_select():
path = filedialog.askdirectory(title='Select folder')
shutil.copyfile("./assets/solutions/database_data.dat", f'{path}/database_data.dat')
statusbar.set('Backup complete')
########################################################################################################################
################################## C H E C K I F F I L E E D I T E D ####################################
########################################################################################################################
def check_if_file_edited():
def check():
current_text = text_area.get("1.0", "end-1c")
if hash(current_text) != hash(content):
statusbar.set('Changed version')
else:
statusbar.set("Unchanged version")
cscroll()
text_area = tk.Text(scroll)
text_area.grid(row=0, column=0)
content = "Squirrels are the greatest animals!"
text_area.insert("1.0", content)
text_area.bind("<KeyRelease>", lambda x: check())
########################################################################################################################
####################################### C H E C K I N P U T D A T E ########################################
########################################################################################################################
import re
def check_input_date(date):
date_pattern = re.compile(r"^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")
date_checked = date_pattern.fullmatch(date)
return date_checked
########################################################################################################################
####################################### C H E C K I N P U T T I M E ########################################
########################################################################################################################
import re
def check_input_time(time):
time_pattern = re.compile(r"^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$")
time_check = time_pattern.fullmatch(time)
return time_check
########################################################################################################################
###################################### C H E C K I N P U T E M A I L ########################################
########################################################################################################################
import re
def check_input_email(email_address):
email_str = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'
return re.search(email_str, email_address)
########################################################################################################################
###################################### C H E C K I N P U T P R I C E #######################################
########################################################################################################################
import re
def check_input_price(price):
price_pattern = re.compile(r"^\d+([.]\d{1,2})?$")
price_checked = price_pattern.fullmatch(price)
return price_checked
########################################################################################################################
################# C H I L D R E N - C L E A R A L L I N S C R O L L W I N D O W ################
########################################################################################################################
def cscroll():
for child in scroll.winfo_children():
child.destroy()
########################################################################################################################
############### C H I L D R E N - C L E A R A L L I N S E L E C T E D W I N D O W ##############
########################################################################################################################
def c(selected_widget):
for child in selected_widget.winfo_children():
child.destroy()
########################################################################################################################
####################### C H I L D R E N - E D I T A L L I N A W I N D O W ######################
########################################################################################################################
def edit_children():
for child in scroll.winfo_children():
child.grid_configure(pady=1)
child.config(foreground='green') # .config is responsible for setting of label creation
child.configure(font=('Arial', 40)) # .configure is responsible for grid settings
########################################################################################################################
################## C H I L D R E N - F I N D W I D G E T S B Y S T R I N G I D #################
########################################################################################################################
def find_children():
cscroll()
tk.Label(scroll).pack()
ttk.Label(scroll).pack()
tk.Button(scroll).pack()
ttk.Button(scroll).pack()
tk.Frame(scroll).pack()
ttk.Frame(scroll).pack()
tk.Entry(scroll).pack()
ttk.Entry(scroll).pack()
tk.Text(scroll).pack()
ttk.Checkbutton(scroll).pack()
tk.Checkbutton(scroll).pack()
ttk.Combobox(scroll).pack()
ttk.Separator(scroll).pack()
tk.Listbox(scroll).pack()
ttk.Radiobutton(scroll).pack()
tk.Radiobutton(scroll).pack()
ttk.Scale(scroll).pack()
tk.Scale(scroll).pack()
for i, each_child in enumerate(scroll.winfo_children()):
print(str(type(each_child)))
if str(type(each_child)) == "<class 'tkinter.Text'>":
statusbar.set(f"Widget number {i} is a text widget.")
'''
P R I N T R E S U L T:
<class 'tkinter.Label'>
<class 'tkinter.ttk.Label'>
<class 'tkinter.Button'>
<class 'tkinter.ttk.Button'>
<class 'tkinter.Frame'>
<class 'tkinter.ttk.Frame'>
<class 'tkinter.Entry'>
<class 'tkinter.ttk.Entry'>
<class 'tkinter.Text'>
<class 'tkinter.ttk.Checkbutton'>
<class 'tkinter.Checkbutton'>
<class 'tkinter.ttk.Combobox'>
<class 'tkinter.ttk.Separator'>
<class 'tkinter.Listbox'>
<class 'tkinter.ttk.Radiobutton'>
<class 'tkinter.Radiobutton'>
<class 'tkinter.ttk.Scale'>
<class 'tkinter.Scale'>
'''
########################################################################################################################
##################### C H I L D R E N - R E A D T E X T F R O M E N T R I E S #####################
########################################################################################################################
def read_from_text_children():
list_from_entries = []
def read_and_create_list():
for child in popup_window.winfo_children():
if str(type(child)) == "<class 'tkinter.Text'>":
word = child.get("1.0", "end-1c")
list_from_entries.append(word)
autopopulate(list_from_entries)
popup_window.destroy()
popup_window = tk.Toplevel()
popup_window.columnconfigure(0, weight=1)
tk.Text(popup_window, height=1).grid(row=0, column=0, padx=10, pady=(10, 0), sticky="EW")
tk.Text(popup_window, height=1).grid(row=1, column=0, padx=10, pady=(5, 0), sticky="EW")
tk.Text(popup_window, height=1).grid(row=2, column=0, padx=10, pady=(5, 0), sticky="EW")
tk.Text(popup_window, height=1).grid(row=3, column=0, padx=10, pady=(5, 0), sticky="EW")
tk.Text(popup_window, height=1).grid(row=4, column=0, padx=10, pady=(5, 10), sticky="EW")
frame_buttons = ttk.Frame(popup_window)
frame_buttons.grid(row=5, column=0, sticky="EW")
frame_buttons.columnconfigure(0, weight=1)
popup_add_button = ttk.Button(frame_buttons, text='Read', command=lambda: read_and_create_list())
popup_add_button.grid(row=0, column=1, sticky="w")
popup_cancel_button = ttk.Button(frame_buttons, text="Cancel", command=lambda: popup_window.destroy())
popup_cancel_button.grid(row=0, column=2, sticky="w")
########################################################################################################################
################# C H I L D R E N - S E L E C T A C T I V E N O T E B O O K T A B #################
########################################################################################################################
def select_active_child():
def check():
active_tab = scroll.nametowidget(notebook.select())
statusbar.set(active_tab)
cscroll()
notebook = ttk.Notebook(scroll)
notebook.grid(column=0, row=0, sticky="NEWS")
tab_1 = ttk.Frame(notebook)
notebook.add(tab_1, text="Tab One")
tab_2 = ttk.Frame(notebook)
notebook.add(tab_2, text="Tab Two")
ttk.Button(scroll, text="Active tab", command=check).grid(row=1, column=0, sticky="EW")
########################################################################################################################
########################## C O P Y L A B E L T E X T T O C L I P B O A R D ###########################
########################################################################################################################
def copy_to_clipboard():
def clear_clpb_and_copy(source):
root.clipboard_clear()
root.clipboard_append(source)
statusbar.set(f'{source} copied to clipboard')
cscroll()
label_to_copy_from = ttk.Label(scroll, text=f'\n\n\n\nCLICK ME, COPY ME! 🐿', font=("Calibri", 40), anchor="center", width=40)
label_to_copy_from.grid(row=0, column=0, sticky="NEWS")
label_to_copy_from.bind("<Button-1>", lambda *args: clear_clpb_and_copy(label_to_copy_from['text']))
########################################################################################################################
################ D I S P L A Y I N I T I A L A N D U P D A T E D R O O T S I Z E S ################
########################################################################################################################
def window_size():
def updated_size(event):
statusbar.set(f"Initial W={initial_width}, H={initial_height} :: New W={event.width}, H={event.height}")
root.update_idletasks()
initial_width = root.winfo_width()
initial_height = root.winfo_height()
root.bind("<Configure>", updated_size)
########################################################################################################################
####################### D I S P L A Y W I N D O W S I Z E A N D P O S I T I O N ######################
########################################################################################################################
def display_window_size_and_position():
def update_window_data():
window_data_label.config(text=f"All data: {root.winfo_geometry()}\n"
f"Window width: {root.winfo_width()}\n"
f"Window height: {root.winfo_height()}\n"
f"Window position X: {root.winfo_x()}\n"
f"Window position Y: {root.winfo_y()}")
cscroll()
window_data_label = tk.Label(scroll, text='')
window_data_button = tk.Button(scroll, text='Display current window data', command=update_window_data)
window_data_button.pack(pady=20)
window_data_label.pack(pady=20)
########################################################################################################################
############################### D Y N A M I C A L L Y R E S I Z E W I N D O W ##############################
########################################################################################################################
def resize_window():
def accept_resize():
try:
root.geometry(f'{window_width.get()}x{window_height.get()}')
statusbar.set(f"New width = {window_width.get()} / New height = {window_height.get()}")
except:
statusbar.set('Enter values')
cscroll()
window_width = tk.Entry(scroll)
window_width.pack()
window_height = tk.Entry(scroll)
window_height.pack()
ttk.Button(scroll, text='Resize', command=lambda: accept_resize()).pack()
########################################################################################################################
########## P O S I T I O N W I N D O W I N T H E M I D D L E O F T H E S C R E E N ##########
########################################################################################################################
def position():
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
app_width = 1400
app_height = 850
x = int((screen_width / 2) - (app_width / 2))
y = int((screen_height / 2) - (app_height / 2))
root.geometry(f"{app_width}x{app_height}+{x}+{y}")
########################################################################################################################
#################################### R E M O V E S I N G L E W I D G E T ###################################
########################################################################################################################
def remove_widget():
cscroll()
ttk.Button(scroll, text="Remove Widget Label", command=lambda: label_to_remove.grid_forget()).grid(row=0, column=0)
label_to_remove = tk.Label(scroll, text="🏵", font=("Calibri, 100"))
label_to_remove.grid(row=1, column=0)
########################################################################################################################
##################################### S A V E / L O A D - P I C K L E ######################################
########################################################################################################################
import pickle
try:
data_save = open("./assets/solutions/DATA_SAMPLE.DAT", "rb")
SAMPLE_LIST = pickle.load(data_save)
data_save.close()
except:
SAMPLE_LIST = ['🦍', '🦏', '🐈', '🐿', '🐳', '🐎', '🐋', '🐕', '🦇', '🦊']
def save_all():
cscroll()
data_save = open("./assets/solutions/DATA_SAMPLE.DAT", "wb")
pickle.dump(SAMPLE_LIST, data_save)
data_save.close()
statusbar.set("All changes saved")
########################################################################################################################
############################################### T I M E S T A M P ################################################
########################################################################################################################
def timestamp():
return datetime.datetime.now().strftime('%Y%m%d%H%M%S')
########################################################################################################################
############################################### T H R E A D I N G ################################################
########################################################################################################################
def task_threading():
cscroll()
# Import threading
import threading
# This function, without threading would stop the app for 5 seconds
def five_seconds():
import time
time.sleep(5)
statusbar.set("5 Seconds is up!")
# Without threading this function wouldn't run until first function (if run) finishes
def random_number():
statusbar.set(f"Button pressed")
# Call function through threading
tk.Button(scroll, text='5 Seconds', command=lambda: threading.Thread(target=five_seconds).start()).pack(pady=20)
tk.Button(scroll, text="Try Pressing", command=random_number).pack(pady=20)
########################################################################################################################
########################################################################################################################
################################################# ##################################################
################################################# W I D G E T S ##################################################
################################################# ##################################################
########################################################################################################################
########################################################################################################################
def widget_checkbutton():
def print_selection():
statusbar.set(f'Checkbutton 1 is in position {option1_checkbutton.get()}. / Checkbutton 2 is in position {option2_checkbutton.get()}.')
option1_checkbutton = tk.StringVar()
option2_checkbutton = tk.StringVar()
cscroll()
ttk.Checkbutton(scroll, text='Option 1', variable=option1_checkbutton, onvalue='On', offvalue='Off', command=print_selection).pack(padx=50, pady=50)
ttk.Checkbutton(scroll, text='Option 2', variable=option2_checkbutton, onvalue='On', offvalue='Off', command=print_selection).pack(padx=50, pady=50)
def widget_combobox():
def print_selection(event):
statusbar.set(f'Combobox current selections is: {option_combobox.get()}.')
option_combobox = tk.StringVar()
cscroll()
combobox = ttk.Combobox(scroll, textvariable=option_combobox, font=("Calibri", 14), state='readonly')
combobox['values'] = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
combobox.pack(padx=50, pady=50)
combobox.bind("<<ComboboxSelected>>", print_selection)
def widget_dropdown_box():
clicked = tk.StringVar()
cscroll()
options = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
clicked.set(options[0])
tk.OptionMenu(scroll, clicked, *options).pack() # without * before options I would get all list as one string
tk.Button(scroll, text="Show Selection", command=lambda: tk.Label(scroll, text=clicked.get()).pack()).pack()
def entry_as_password():
entry_password = tk.StringVar()
cscroll()
entry = tk.Entry(scroll, textvariable=entry_password, show="*")
entry.pack()
tk.Button(scroll, text="Display Password", command=lambda: statusbar.set(f"Password: {entry_password.get()}")).pack()
def entry_auto_delete():
cscroll()
entry_text = tk.Entry(scroll)
entry_text.insert(0, "Enter password...")
entry_text.pack()
entry_text.bind("<Button-1>", lambda event: entry_text.delete(0, "end"))
def widget_labelframe():
# https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/labelframe.html
cscroll()
label_frame = tk.LabelFrame(scroll,
text='Label Frame',
labelanchor='n',
background='white',
padx=10,
pady=10,
width=340,
height=205)
label_frame.grid(row=0, column=0, sticky="NW", padx=5, pady=5)
def widget_label_wrap():
cscroll()
label_wrap = tk.Label(scroll,
text=('Just add wrap=width_of_screen_in_pixels. To wrap text in canvas set width to number of characters: canvas.create_text(x, y, width=80)\t' * 20),
wrap=680,
background='white',
padx=10,
pady=10)
label_wrap.grid(row=0, column=0, sticky="NW", padx=5, pady=5)
def widget_listbox():
def print_selection(event):
selected_items = listbox.curselection()
delete_element_button.config(text=f'Delete selected: {SAMPLE_LIST[selected_items[0]]}')
for each_item in selected_items:
statusbar.set(f'Currently selected animals are: {listbox.get(each_item)}.')
animals = tk.StringVar(value=SAMPLE_LIST)
cscroll()
listbox = tk.Listbox(scroll, listvariable=animals, height=10, font=("Calibri", 24))
listbox["selectmode"] = "extended" # skip to allow only one selection
listbox.pack(padx=50, pady=50)
listbox.bind("<<ListboxSelect>>", print_selection)
delete_element_button = ttk.Button(scroll, text=f'Delete selected', command=lambda: listbox.delete("anchor"))
delete_element_button.pack()
ttk.Button(scroll, text=f'Delete all', command=lambda: listbox.delete(0, "end")).pack()
def widget_listbox_advanced_with_scrollbar():
cscroll()
frame_to_insert_widget = scroll
listbox_sample_list = ['🐳', '🐎', '🐕', '🦇', '🦊']
animals = tk.StringVar(value=listbox_sample_list)
listbox = tk.Listbox(frame_to_insert_widget, listvariable=animals, height=10, font=("Calibri", 24))
listbox["selectmode"] = "single" # skip to allow only one selection
listbox.selection_set(first=0) # select the first item
listbox.insert("end", f"Autoselected item: {listbox.selection_get()}")
listbox.grid(row=0, column=0, sticky="news")
listbox.bind("<<ListboxSelect>>", lambda event: print(
listbox.insert("end", f"Clicked item: {listbox_sample_list[listbox.curselection()[0]]}")))
# listbox.bind("<Double-Button-1>", lambda event: print(f"{listbox.curselection()} doubleclicked!"))
# Entire widget:
listbox.config(width=20)
listbox.config(foreground="black") # Font colour
listbox.config(background="white")
listbox.config(highlightcolor='#3c3c3c') # colour of the frame of the entire widget when selected
listbox.config(highlightthickness=0) # thickness of the widget frame when selected
listbox.config(highlightbackground="white") # colour of the widget frame when not selected
listbox.config(relief="flat")
# Individual entries
listbox.config(activestyle='none') # do not underline selected items (dotbox, none, or underline)
listbox.config(selectborderwidth=0) # This is border thickness of individual entries
listbox.config(selectbackground="#3c3c3c") # selected background colour
listbox.config(selectforeground="white") # selected font colour
scrollbar = ttk.Scrollbar(frame_to_insert_widget, orient="vertical", command=listbox.yview)
scrollbar.grid(row=0, column=1, sticky="NS")
listbox["yscrollcommand"] = scrollbar.set
def widget_notebook(): # Important options: notebook.forget(tab_id) / notebook.hide(tab_id) / notebook.select(tab_id)
cscroll()
notebook = ttk.Notebook(scroll)
notebook.grid(column=0, row=0, sticky="NEWS")
tab_1 = ttk.Frame(notebook, width=1000, height=500)
notebook.add(tab_1, text="Tab One")
tab_2 = ttk.Frame(notebook, width=1000, height=500)
notebook.add(tab_2, text="Tab Two")
def paned_window():
# http://effbot.org/tkinterbook/panedwindow.htm
cscroll()
# New frame to force scroll to a larger size
large_frame = tk.Frame(scroll)
large_frame.grid(row=0, column=0, sticky="NEWS")
large_frame.columnconfigure(0, minsize=500, weight=1)
large_frame.rowconfigure(0, minsize=500, weight=1)
panel_1 = tk.PanedWindow(large_frame, bd=4, relief='flat', bg='grey80')
panel_1.grid(row=0, column=0, sticky="NEWS") # Only the first one should use grid or pack
label_left = tk.Label(panel_1, text="PANEL 1")
# label_left.pack() would add it on top of the panel, add() function makes it a part of the panel (same colour)
panel_1.add(label_left)
# The second panel I should position inside the first one
panel_2 = tk.PanedWindow(panel_1, orient="vertical", bd=4, relief='flat', bg='grey80')
panel_1.add(panel_2)
label_top = tk.Label(panel_2, text="PANEL 2")
panel_2.add(label_top)
label_bottom = tk.Label(panel_2, text="PANEL 3")
panel_2.add(label_bottom)
def widget_progress_bar():
def stop():
progress.stop() # this is how to stop the progress bar from animating
cscroll()
progress = ttk.Progressbar(scroll, orient="horizontal", length=500, mode="determinate")
progress.pack(pady=50)
# mode="indeterminate" full bar
# mode="indeterminate" dot
progress['value'] = 20 # set value to 20
progress.start(10) # make it animate, 10 points increments. This is just an animation, showing that something is happening
tk.Button(scroll, text='Stop', command=stop).pack()
def widget_radiobutton():
def print_selection():
statusbar.set(f'This is your animal: {option_radiobutton.get()}')
cscroll()
option_radiobutton = tk.StringVar()
ttk.Radiobutton(scroll, text="My favourite animal is a squirrel", variable=option_radiobutton, value="🐿", command=print_selection).grid(row=0, column=0, padx=50, pady=25)
ttk.Radiobutton(scroll, text="My favourite animal is a koala", variable=option_radiobutton, value="🐨", command=print_selection).grid(row=1, column=0, padx=50, pady=25)
ttk.Radiobutton(scroll, text="My favourite animal is a shark", variable=option_radiobutton, value="🦈", command=print_selection).grid(row=2, column=0, padx=50, pady=25)
def widget_scales():
def print_selection(event):
statusbar.set(f"Current selected value is: {option_scales.get()}")
cscroll()
option_scales = tk.DoubleVar()
tk.Scale(scroll, orient="horizontal", from_=0, to=10, variable=option_scales, command=print_selection, length=500, label='Scales 0 - 10').grid(row=0, column=0, sticky="NEWS", padx=50, pady=50)
tk.Label(scroll, textvariable=option_scales).grid(row=1, column=0, sticky="NEWS", padx=50, pady=50)
# Options: orient='horizontal'
def widget_scrollbar():
cscroll()
text = tk.Text(scroll)
text.grid(row=0, column=0, sticky="NEWS")
text.insert("1.0", f'{str(SAMPLE_LIST)}\n' * 100)
scrollbar = ttk.Scrollbar(scroll, orient="vertical", command=text.yview)
scrollbar.grid(row=0, column=1, sticky="NS")
text["yscrollcommand"] = scrollbar.set
def widget_spinbox():
def print_selection():
statusbar.set(f"Current selected value is: {option_spinbox.get()}")
cscroll()
option_spinbox = tk.IntVar(value=5)
spinbox = ttk.Spinbox(
scroll,
from_=0, to=10, # I can also use values=(5,10,15,25,30)
textvariable=option_spinbox,
wrap=True, # start over when limit is reached
command=print_selection)
spinbox.grid(row=0, column=0, padx=50, pady=50)
def widget_treeview():
def delete_all():
for record in tree.get_children():
tree.delete(record)
def delete_selected():
x = tree.selection()[0]
tree.delete(x)
def tree_action(event):
selected_id = tree.selection()
selected_item = tree.item(selected_id, "text")
statusbar.set(selected_item)
def change_colours():
# Create striped row tags, to make it work I need to select a style
style.theme_use("clam")
style.configure("Treeview", background="silver", foreground='black', rowheight=50, fieldbackground='silver')
style.map("Treeview", background=[('selected', 'green')])
tree.tag_configure('oddrow', background='white')
tree.tag_configure('evenrow', background='lightblue')
count = 0
for each_row in list_emoji:
if count % 2 == 0: # this is how I tag entries with different colours
tree.insert(parent=misi_misia, index='end', text="Emoticons", values=(each_row[0], each_row[0], each_row[0]), tags=('evenrow', ))
else:
tree.insert(parent=misi_misia, index='end', text="Emoticons", values=(each_row[0], each_row[0], each_row[0]), tags=('oddrow', ))
count += 1
'''Treeview modes:
my_tree.config(selectmode=" ... ")
none - selecting disabled
extended - (default) select multiple items with control
browse - select only one item, even if controll pressed'''
cscroll()
style = ttk.Style(root)
style.configure("Treeview", rowheight=50)
tree_frame = tk.Frame(scroll)
tree_frame.grid(row=0, column=0, sticky="NEWS")
tree_frame.columnconfigure(0, minsize=1000, weight=1)
tree_scroll = ttk.Scrollbar(tree_frame)
tree_scroll.grid(row=0, column=1, sticky="NS")
tree = ttk.Treeview(tree_frame, yscrollcommand=tree_scroll.set)
tree_scroll.config(command=tree.yview)
# Define Columns
tree["columns"] = ("1", "2", "3")
'''
tree["show"] = "headings"
The first empty column is the identifier, I can disable it using tree["show"] = "headings"
I can also leave it and replce it with an image
'''
# Format Columns
tree.column("#0", width=50)
tree.column("1", width=90, minwidth=90, anchor="c")
tree.column("2", width=200, minwidth=100, anchor="c")
tree.column("3", width=150, anchor="c")
# Create Headings
tree.heading("1", text="Category")
tree.heading("2", text="Priority")
tree.heading("3", text="Added")
# Add Data
# Level 1
misi = tree.insert(parent="", index='end', text=" Renatka", image=picture_renatka)
tree.insert(misi, "end", text='Test', values=("Personal", "High", "2020-08-12"))
misia = tree.insert(parent="", index='end', text=" Krzysio", image=picture_krzysio)
tree.insert(parent=misia, index="end", text='Test', values=("Coding", "Low", "2020-08-12"))
tree.insert(parent=misia, index="end", text='Test', values=("Personal", "High", "2020-08-12"))
misi_misia = tree.insert(parent="", index='end', text=" Wspólne", image=picture_both)
tree.insert(parent=misi_misia, index="end", text='Test', values=("House", "Medium", "2020-08-12"))
tree.grid(row=0, column=0, sticky="NEWS")
ttk.Button(tree_frame, text="🗑 All", command=lambda: delete_all()).grid(row=1, column=0, sticky="EW")
ttk.Button(tree_frame, text="🗑 Selected", command=lambda: delete_selected()).grid(row=2, column=0, sticky="EW")
ttk.Button(tree_frame, text="Change Colours", command=lambda: change_colours()).grid(row=3, column=0, sticky="EW")
tree.bind("<Double-1>", tree_action)
########################################################################################################################
########################################################################################################################
######################################### #########################################
######################################### O T H E R F U N C T I O N S #########################################
######################################### #########################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
########################################### B I N D A C T I O N S #############################################
########################################################################################################################
def bind_actions():
cscroll()
action_entry = tk.Entry(scroll)
action_entry.pack()
action_entry.bind("<Button-1>", lambda event: statusbar.set("LMB Clicked"))
action_entry.bind("<Button-2>", lambda event: statusbar.set("MMB Clicked"))
action_entry.bind("<Button-3>", lambda event: statusbar.set("RMB Clicked"))
action_entry.bind("<Enter>", lambda event: statusbar.set("Mouse over"))
action_entry.bind("<Leave>", lambda event: statusbar.set("Mouse away"))
action_entry.bind("<FocusIn>", lambda event: statusbar.set("Selected with tab"))
action_entry.bind("<FocusOut>", lambda event: statusbar.set("Deselected with tab"))
action_entry.bind("<Return>", lambda event: statusbar.set("Enter Key"))
action_entry.bind("<Key>", lambda event: statusbar.set(f"{event.char} clicked"))
# event.char will display key pressed when "<Key>" binding used
########################################################################################################################
########################################## C O L O U R P I C K E R ############################################
########################################################################################################################
from tkinter import colorchooser
def pick_colour():
cscroll()
my_colour = colorchooser.askcolor()
tk.Label(scroll, text=f'You selected: {my_colour[-1]}', bg=my_colour[-1], font=("Calibri", 40)).pack()
########################################################################################################################
#################################################### F O N T S ###################################################
########################################################################################################################
from tkinter import font
def tkinter_fonts():
def copy_font_name(font_name):
root.clipboard_clear()
root.clipboard_append(font_name)
def create_font_labels(i, selected_font):
my_font = font.Font(family=selected_font, size=24)
font_label = tk.Label(scroll, text=f"{selected_font} 1234568790", font=my_font, anchor='w')
font_label.grid(row=i, column=0, sticky="EW", padx=10)
font_label.bind("<Button-1>", lambda event: copy_font_name(selected_font))
cscroll()
for i, each_font in enumerate(font.families()):
create_font_labels(i, each_font)
########################################################################################################################
############################################ O P E N W E B S I T E ############################################
########################################################################################################################
import webbrowser
def open_website():
cscroll()
tk.Button(scroll, text="Google", command=lambda: webbrowser.open("https://google.com/")).pack()
########################################################################################################################
############################ P L A Y S O U N D S U S I N G P L A Y S O U N D ############################
########################################################################################################################
from playsound import playsound
import threading
def play_sound_playsound():
def play_now():
playsound('./assets/solutions/music.mp3')
cscroll()
# Threading used, because otherwise app would become unresponsive for the duration of music
ttk.Button(scroll, text="Play music", command=lambda: threading.Thread(target=play_now).start()).pack(pady=20)
########################################################################################################################
############################### P L A Y S O U N D S U S I N G P Y G A M E ###############################
########################################################################################################################
# pip install pygame
def play_sound_pygame():
def play_song():
pygame.mixer.music.load("./assets/solutions/stormwind.mp3")
pygame.mixer.music.play(loops=0) # loops - number of time play
# Display song length
from mutagen.mp3 import MP3
audio_file = MP3("./assets/solutions/stormwind.mp3")
song_length = float(audio_file.info.length)
import time
song_length_as_time = time.strftime('%H:%M:%S', time.gmtime(song_length))
statusbar.set(f"Song length: {song_length_as_time}")
def stop_song():
pygame.mixer.music.stop()
import pygame
pygame.mixer.init() # Initialize Pygame sound module
cscroll()
tk.Button(scroll, text='Play song', command=play_song).pack(pady=20)
tk.Button(scroll, text='Stop', command=stop_song).pack(pady=20)
########################################################################################################################
####################################### R U N D O S C O M M A N D S ########################################
########################################################################################################################
import os
def run_dos_commands():
def dos_command(command, option):
try:
if option == 'remain':
os.system(f'cmd /k "{command}"')
elif option == 'terminate':
os.system(f'cmd /k "{command}"')
except:
statusbar.set("Error")
cscroll()
entry_command = ttk.Entry(scroll)
entry_command.pack()
entry_option = ttk.Entry(scroll)
entry_option.pack()
tk.Button(scroll,
text='Run command & option (remain or terminate',
command=lambda: dos_command(entry_command.get(), entry_option.get())).pack()
########################################################################################################################
########################################################################################################################
######################################### ##########################################
######################################### T I M E A N D D A T E S ##########################################
######################################### ##########################################
########################################################################################################################
########################################################################################################################
########################################################################################################################
###################################### C O U N T D O W N T I M E R #########################################
########################################################################################################################
def timer_build_ui_and_start():
import math
global my_timer
my_timer = None
def timer_count_down_reset():
global my_timer
root.after_cancel(my_timer)
timer_label['text'] = f'00:00'
timer_start_button['state'] = 'normal'
def timer_count_down_start(count=60):
global my_timer
timer_start_button['state'] = 'disabled'
count_min = math.floor(count / 60)
count_sec = count % 60
if count_sec < 10:
count_sec = f"0{count_sec}"
timer_label['text'] = f'{count_min}:{count_sec}'
if count > 0:
my_timer = root.after(1000, timer_count_down_start, count-1)
else:
statusbar.set("Countdown finished!")
cscroll()
timer_label = tk.Label(scroll, text="Timer", font=('Calibri', 40))
timer_label.grid(row=0, column=1, sticky='ew')
timer_start_button = tk.Button(scroll, text='Start', bg='white', borderwidth=0, width=7, command= lambda: timer_count_down_start(15))
timer_start_button.grid(column=0, row=2)
tk.Button(scroll, text='Reset', bg='white', borderwidth=0, width=7, command= timer_count_down_reset).grid(column=2, row=2)
########################################################################################################################
######################################### D A T E S F U N C T I O N S #########################################
########################################################################################################################
import datetime
from dateutil.relativedelta import relativedelta
import calendar
def dates():
# Date and Time
current_date = datetime.date.today() # print: 2022-10-31 | type: <class 'datetime.date'>
current_date_and_time = datetime.datetime.now() # print: 2022-10-31 23:43:06.346288 | type: <class 'datetime.date'>
add_one_year_one_month_one_day_to_current_date = datetime.date.today() + relativedelta(years=1, months=1, days=1) # print: 2023-12-01 | type: <class 'datetime.date'>
# Day
current_day_of_the_month = datetime.date.today().day # print: 31 | type: <class 'int'>
tomorrow = datetime.date.today() + relativedelta(days=1) # print: 2022-11-01 | type: <class 'datetime.date'>
# Week
name_day_of_the_week = calendar.day_name[datetime.date.today().weekday()] # print: Monday | type: <class 'str'>
# Month
current_month_number = datetime.date.today().month # print: 10 | type: <class 'int'>
number_of_days_in_this_month = calendar.monthrange(datetime.date.today().year, datetime.date.today().month)[-1] # print: 31 | type: <class 'int'>
days_left_this_month = (calendar.monthrange(datetime.date.today().year, datetime.date.today().month)[-1]) - datetime.date.today().day # print: 0 | type: <class 'int'>
next_month_date_one_month_added = datetime.date.today() + relativedelta(months=1) # print: 2022-11-30 | type: <class 'datetime.date'>
current_month_first_day_date = datetime.datetime.now().date().replace(day=1) # print: 2022-10-01 | type: <class 'datetime.date'>
previous_month_date_one_month_substracted = datetime.date.today() - relativedelta(months=1) # print: 2022-09-30 | type: <class 'datetime.date'>
month_previous_number = datetime.date.today().month - 1 # print: 9 | type: <class 'int'>
previous_month_first_day_date = (datetime.date.today() - relativedelta(months=1)).replace(day=1) # print: 2022-09-01 | type: <class 'datetime.date'>
# Year
current_year = datetime.date.today().year # print: 2022 | type: <class 'int'>
current_year_start = datetime.datetime.now().date().replace(month=1, day=1) # print: 2022-01-01 | type: <class 'datetime.date'>
number_of_days_passed_in_this_year = datetime.datetime.now().timetuple().tm_yday # print: 304 | type: <class 'int'>
number_of_days_in_this_year = 365 + calendar.isleap(datetime.date.today().year) # print: 365 | type: <class 'int'>
number_of_days_remaining_in_this_year = (365 + calendar.isleap(datetime.date.today().year)) - (datetime.datetime.now().timetuple().tm_yday) # print: 61 | type: <class 'int'>
same_date_as_today_but_next_year = datetime.date.today() + relativedelta(years=1) # print: 2023-10-31 | type: <class 'datetime.date'>
next_year_just_the_number = (datetime.date.today() + relativedelta(years=1)).year # print: 2023 | type: <class 'int'>
# Other
timestamp_ymdhms = current_date_and_time.strftime('%Y%m%d%H%M%S') # print: 20221031235546 | type: <class 'str'>
string_to_date = datetime.datetime.strptime('2020-01-01', '%Y-%m-%d').date() # print: 2020-01-01 | type: <class 'datetime.date'>
dates_text = '''
# Date and Time
current_date \t = datetime.date.today() \t # print: 2022-10-31 | type: <class 'datetime.date'>
current_date_and_time \t = datetime.datetime.now() \t # print: 2022-10-31 23:43:06.346288 | type: <class 'datetime.date'>
add_one_year_one_month_one_day_to_current_date \t = datetime.date.today() + relativedelta(years=1, months=1, days=1) \t # print: 2023-12-01 | type: <class 'datetime.date'>
# Day
current_day_of_the_month \t = datetime.date.today().day \t # print: 31 | type: <class 'int'>
tomorrow \t = datetime.date.today() + relativedelta(days=1) \t # print: 2022-11-01 | type: <class 'datetime.date'>
# Week
name_day_of_the_week \t = calendar.day_name[datetime.date.today().weekday()] \t # print: Monday | type: <class 'str'>
# Month
current_month_number \t = datetime.date.today().month \t # print: 10 | type: <class 'int'>
number_of_days_in_this_month \t = calendar.monthrange(datetime.date.today().year, datetime.date.today().month)[-1] \t # print: 31 | type: <class 'int'>
days_left_this_month \t = (calendar.monthrange(datetime.date.today().year, datetime.date.today().month)[-1]) - datetime.date.today().day \t # print: 0 | type: <class 'int'>
next_month_date_one_month_added \t = datetime.date.today() + relativedelta(months=1) \t # print: 2022-11-30 | type: <class 'datetime.date'>
current_month_first_day_date \t = datetime.datetime.now().date().replace(day=1) \t # print: 2022-10-01 | type: <class 'datetime.date'>
previous_month_date_one_month_substracted \t = datetime.date.today() - relativedelta(months=1) \t# print: 2022-09-30 | type: <class 'datetime.date'>
month_previous_number \t = datetime.date.today().month - 1 \t # print: 9 | type: <class 'int'>
previous_month_first_day_date \t = (datetime.date.today() - relativedelta(months=1)).replace(day=1) \t # print: 2022-09-01 | type: <class 'datetime.date'>
# Year
current_year \t = datetime.date.today().year \t # print: 2022 | type: <class 'int'>
current_year_start \t = datetime.datetime.now().date().replace(month=1, day=1) \t # print: 2022-01-01 | type: <class 'datetime.date'>
number_of_days_passed_in_this_year \t = datetime.datetime.now().timetuple().tm_yday \t # print: 304 | type: <class 'int'>
number_of_days_in_this_year \t = 365 + calendar.isleap(datetime.date.today().year) \t # print: 365 | type: <class 'int'>
number_of_days_remaining_in_this_year \t = (365 + calendar.isleap(datetime.date.today().year)) - (datetime.datetime.now().timetuple().tm_yday) \t # print: 61 | type: <class 'int'>
same_date_as_today_but_next_year \t = datetime.date.today() + relativedelta(years=1) \t # print: 2023-10-31 | type: <class 'datetime.date'>
next_year_just_the_number \t = (datetime.date.today() + relativedelta(years=1)).year \t # print: 2023 | type: <class 'int'>
# Other
timestamp_ymdhms \t = current_date_and_time.strftime('%Y%m%d%H%M%S') \t # print: 20221031235546 | type: <class 'str'>
string_to_date \t = datetime.datetime.strptime('2020-01-01', '%Y-%m-%d').date() \t # print: 2020-01-01 | type: <class 'datetime.date'>
'''
cscroll()
ttk.Label(scroll, text=f"{dates_text}").grid(row=0, column=0, sticky="EW")
############################################# A D D H O U R S #############################################
date_entry = '2020-01-01'
time_entry = '10:00'
# Add hours (I need both date and time given)
user_time = f"{date_entry} {time_entry}:00"
convert_to_datetime = datetime.datetime.strptime(user_time, '%Y-%m-%d %H:%M:%S')
add_one_hour = convert_to_datetime + relativedelta(hours=1)
############################ CALCULATE MONTHS BETWEEN NOW AND THE BEGINNING OF THE YEAR ############################
# 1.) Create strings for each month starting with the first day
list_of_months_string = [] # ['2020-1-01', '2020-2-01', '2020-3-01', '2020-4-01']
for each_month in range(current_month_number):
list_of_months_string.append(f"{current_year}-{each_month+1}-01")
# 2.) Create list of datetime ranges (first and last day of month) for each month from the previous list
list_of_month_ranges_datetime = [] # [[datetime.date(2020, 1, 1), datetime.date(2020, 1, 31)], ... and so on
for each_month_date in list_of_months_string:
list_of_month_ranges_datetime.append([datetime.datetime.strptime(each_month_date, '%Y-%m-%d').date(), datetime.datetime.strptime(each_month_date, '%Y-%m-%d').date() + relativedelta(months=1, days=-1)])
# 3.) Use the previous list to display each available month's name
list_of_month_names = [] # ['January', 'February', 'March', 'April']
for each_month_datetime in list_of_month_ranges_datetime:
list_of_month_names.append(each_month_datetime[0].strftime("%B"))
########################################################################################################################
################################## D A T E S F U N C T I O N S S I M P L E #################################
########################################################################################################################
# https://docs.python.org/3/library/time.html
# https://docs.python.org/3/library/time.html
import time
def time_calculations_simple():
def calculate_time():
year = time.strftime("%Y")
month = time.strftime("%m")
day = time.strftime("%d")
month_name = time.strftime("%B")
day_of_week = time.strftime("%A")
hour = time.strftime("%H")
minute = time.strftime("%M")
second = time.strftime("%S")
timezone = time.strftime("%Z")
auto_hour_minute_second = time.strftime("%X")
my_label.config(text=f"{year}.{month}.{day}\n"
f"{month_name} - {day_of_week}\n"
f"{hour}:{minute}:{second}\n"
f"{auto_hour_minute_second}\n"
f"{timezone}")
my_label.after(1000, calculate_time)
cscroll()
my_label = tk.Label(scroll, text='', font=("Calibri", 24))
my_label.pack(pady=50, padx=50)
calculate_time()
########################################################################################################################
############################################## T I M E S I N C E ##############################################
########################################################################################################################
import datetime
def time_since_event():
def calculate_time_since(date_to_check):
if datetime.date.today() >= date_to_check:
days_since = (datetime.date.today() - date_to_check).days
statusbar.set(f"Days since: {days_since}")
time_since_label['text'] = '''
def calculate_time_since(date_to_check):
\tif datetime.date.today() >= date_to_check:
\t\tdays_since = (datetime.date.today() - date_to_check).days
\t\treturn days_since
calculate_time_since(datetime.date(year=1981, month=9, day=28))
print: 15009
type: <class 'int'>
'''
cscroll()
time_since_label = tk.Label(scroll, text='', font=("Calibri", 10), anchor='nw', justify='left')
time_since_label.pack(pady=20, padx=20)
calculate_time_since(datetime.date(year=1981, month=9, day=28))
########################################################################################################################
############################################## T I M E U N T I L ##############################################
########################################################################################################################
def time_until_event():
def calculate_time_until(date_to_check):
if datetime.date.today() > date_to_check: # Check if date isn't in the past
date_to_check = date_to_check.replace(year=datetime.date.today().year) # if it is change it's year to current year
if datetime.date.today() > date_to_check: # Check again after changing year if days or months are still in the past
date_to_check = date_to_check.replace(year=datetime.date.today() + relativedelta(years=1)) # If yes change the year to next
days_remaining = (date_to_check - datetime.date.today()).days
statusbar.set(f"Days until: {days_remaining}")
time_until_label['text'] = '''
def calculate_time_until(date_to_check):
\t if datetime.date.today() > date_to_check: # Check if date isn't in the past
\t\t date_to_check = date_to_check.replace(year=datetime.date.today().year) # if it is change it's year to current year
\t if datetime.date.today() > date_to_check: # Check again after changing year if days or months are still in the past
\t\t date_to_check = date_to_check.replace(year=datetime.date.today() + relativedelta(years=1)) # If yes change the year to next
\t days_remaining = (date_to_check - datetime.date.today()).days
\t return days_remaining
calculate_time_until(datetime.date(year=2081, month=9, day=28))
print: 21516
type: <class 'int'>
'''
cscroll()
time_until_label = tk.Label(scroll, text='', font=("Calibri", 10), anchor='nw', justify='left')
time_until_label.pack(pady=20, padx=20)
calculate_time_until(datetime.date(year=2081, month=9, day=28))
########################################################################################################################
########################################################################################################################
####################################### #######################################
####################################### S C R O L L A B L E C A N V A S #######################################
####################################### #######################################
########################################################################################################################
########################################################################################################################
class ScrollableFrame(ttk.Frame):
def __init__(self, container, *args, **kwargs):
super().__init__(container, *args, **kwargs)
self.canvas = tk.Canvas(self) # width=250 - to change the width of widget
scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.frame_to_scroll = ttk.Frame(self.canvas)
self.frame_to_scroll.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))
self.frame_to_scroll.bind("<Enter>", self.mouse_on)
self.frame_to_scroll.bind("<Leave>", self.mouse_off)
self.canvas.create_window((0, 0), window=self.frame_to_scroll, anchor="nw")
self.canvas.configure(yscrollcommand=scrollbar.set)
self.canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
def mouse_on(self, event):
self.canvas.bind_all("<MouseWheel>", self.mouse_use)
def mouse_off(self, event):
self.canvas.unbind_all("<MouseWheel>")
def mouse_use(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def configure_scrollable_canvas():
########## CHANGE SCROLLABLE CANVAS BACKGROUND ##########
style = ttk.Style(root)
style.configure("white.TFrame", background='white')
scrollable_canvas.canvas.config(bg='white')
scrollable_canvas.frame_to_scroll.config(style='white.TFrame')
########## SET CANVAS SIZE TO WINDOW SIZE AND ADJUST HEIGHT BY CONTENT ##########
root.update_idletasks()
window_width = root.winfo_width() - 40
number_of_window_items = 20
scrollable_canvas.frame_to_scroll.config(width=window_width)
scrollable_canvas.frame_to_scroll.config(height=60 + (len(range(0, number_of_window_items))) * 25)
scrollable_canvas.frame_to_scroll.grid_propagate(0) # Canvas will no longer adjust it's size automatically
########################################################################################################################
########################################################################################################################
############################################# #############################################
############################################# M A I N W I N D O W #############################################
############################################# #############################################
########################################################################################################################
########################################################################################################################
root = tk.Tk()
root.geometry("1920x1080+700+500")
root.resizable(True, True)
root.title('Solutions')
root.iconbitmap('./assets/solutions/SAMPLE_ICON.ICO')
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
# SCROLLABLE CANVAS #
scrollable_canvas = ScrollableFrame(root)
scrollable_canvas.grid(row=0, column=0, sticky="NEWS")
scroll = scrollable_canvas.frame_to_scroll
########################################################################################################################
#################################################### M E N U #####################################################
########################################################################################################################
def app_menu():
menubar = tk.Menu(root)
root.config(menu=menubar)
root.option_add("*tearOff", False)
######################### A I - A R T I F I C I A L I N T E L L I G E N C E #########################
menu_ai = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='🤖 AI', menu=menu_ai)
menu_ai.add_command(label='Speech Recognition', command=lambda: ai_speech_recognition())
menubar.add_command(label="\u22EE")
################################################### A P I ####################################################
menu_api = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='🧱 API', menu=menu_api)
menu_api.add_command(label='Google Calendar - Print Events', command=lambda: google_calendar_print())
menu_api.add_command(label='Google Calendar - Add Events', command=lambda: google_calendar_add())
menu_api.add_command(label='Google Drive - Create Spreadsheet', command=lambda: google_drive_add())
menu_api.add_command(label='Weather API', command=lambda: weather_api())
menubar.add_command(label="\u22EE")
################################################ C H A R T S #################################################
charts = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📈 Charts', menu=charts)
charts.add_command(label='Doughnut Chart', command=lambda: doughnut_chart())
charts.add_command(label="Simple Graph", command= lambda: simple_graph())
menubar.add_command(label="\u22EE")
############################################### C L A S S E S ################################################
classes = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='🏭 Classes', menu=classes)
classes.add_command(label='Button with Picture', command=lambda: class_button())
classes.add_command(label='Display Attributes of a Widget', command=lambda: Attributes(root, tk.Button()))
classes.add_command(label='Limiter', command=lambda: display_limiter())
classes.add_command(label='My Frame', command=lambda: display_my_frame())
menubar.add_command(label="\u22EE")
################################################# E M A I L ##################################################
email = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Email', menu=email)
email.add_command(label='Email simple with auto address', command=lambda: email_simple())
email.add_command(label='Email advanced with popup text entry', command=lambda: email_advanced())
menubar.add_command(label="\u22EE")
################################################ E X P O R T #################################################
export = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='🚀 Export', menu=export)
export.add_command(label='Export database', command=lambda: backup_database())
export.add_command(label='Export CSV', command=lambda: export_csv())
export.add_command(label='Export PDF', command=lambda: create_pdf())
export.add_command(label='Export TXT', command=lambda: export_txt())
export.add_command(label='Print with default printer', command=lambda: printer_print())
menubar.add_command(label="\u22EE")
#################################### F I L E S A N D F O L D E R S #####################################
files_folders = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Files and Folders', menu=files_folders)
files_folders.add_command(label='Create and Open a New Folder', command=lambda: create_and_open_folder())
files_folders.add_command(label='Create Folders with Unique Y-M-D-H-M-S Names', command=lambda: create_timestamp_folder())
files_folders.add_command(label='Display Absolute Path to a File', command=lambda: absolute_path())
files_folders.add_command(label='Display All Files in a Folder', command=lambda: display_all_files())
files_folders.add_command(label='Display File Name', command=lambda: display_file_name())
files_folders.add_command(label='Display First PNG in a Folder', command=lambda: select_first_png())
files_folders.add_command(label='Open External Program', command=lambda: open_app())
files_folders.add_command(label='Open File', command=lambda: open_file())
menubar.add_command(label="\u22EE")
################################################ I M A G E S #################################################
images_functions = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Images', menu=images_functions)
images_functions.add_command(label='Animate Image', command=lambda: animate_image())
images_functions.add_command(label='Display Image', command=lambda: display_image())
images_functions.add_command(label='Display Image - simple', command=lambda: display_image_simple())
images_functions.add_command(label='Display Image to Fit Window', command=lambda: display_image_adjusted())
images_functions.add_command(label='Image as Background', command=lambda: image_as_background())
images_functions.add_command(label='Image as Background with resize', command=lambda: image_as_background_with_resize())
menubar.add_command(label="\u22EE")
####################################### O T H E R F U N C T I O N S #######################################
other_functions = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Other', menu=other_functions)
other_functions.add_command(label='Bind actions', command=lambda: bind_actions())
other_functions.add_command(label='Colour Picker', command=lambda: pick_colour())
other_functions.add_command(label='Count Down Timer', command=lambda: timer_build_ui_and_start())
other_functions.add_command(label='Dates Functions', command=lambda: dates())
other_functions.add_command(label='Dates Functions - simple', command=lambda: time_calculations_simple())
other_functions.add_command(label='Fonts in TKinter', command=lambda: tkinter_fonts())
other_functions.add_command(label='Open Website', command=lambda: open_website())
other_functions.add_command(label='Play Music using playsound', command=lambda: play_sound_playsound())
other_functions.add_command(label='Play Music using pygame', command=lambda: play_sound_pygame())
other_functions.add_command(label='Run DOS commands', command=lambda: run_dos_commands())
menubar.add_command(label="\u22EE")
######################################## T I M E F U N C T I O N S ########################################
time_functions = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Time', menu=time_functions)
time_functions.add_command(label='Count Down Timer', command=lambda: timer_build_ui_and_start())
time_functions.add_command(label='Dates Functions', command=lambda: dates())
time_functions.add_command(label='Dates Functions - simple', command=lambda: time_calculations_simple())
time_functions.add_command(label='Time Since an event', command=lambda: time_since_event())
time_functions.add_command(label='Time Until an event', command=lambda: time_until_event())
menubar.add_command(label="\u22EE")
######################################### P O P U P W I N D O W S #########################################
popup_windows = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Popup', menu=popup_windows)
popup_windows.add_command(label='Dialog Open File', command=lambda: open_txt())
popup_windows.add_command(label='Dialog Open Many Files', command=lambda: open_many_files())
popup_windows.add_command(label='Dialog Open Directory', command=lambda: open_directory())
popup_windows.add_command(label='Dialog Save File', command=lambda: save_txt())
popup_windows.add_command(label='Messagebox Show Error', command=lambda: messagebox_showerror())
popup_windows.add_command(label='Messagebox Show Info', command=lambda: messagebox_showinfo())
popup_windows.add_command(label='Messagebox Show Warning', command=lambda: messagebox_showwarning())
popup_windows.add_command(label='Messagebox OK Cancel', command=lambda: run_messagebox(messagebox_askokcancel))
popup_windows.add_command(label='Messagebox Retry Cancel', command=lambda: run_messagebox(messagebox_askretrycancel))
popup_windows.add_command(label='Messagebox Yes No', command=lambda: run_messagebox(messagebox_askyesno))
popup_windows.add_command(label='Messagebox Yes No Cancel', command=lambda: run_messagebox(messagebox_askyesnocancel))
popup_windows.add_command(label='Simple Popup Window', command=lambda: simple_popup_window())
popup_windows.add_command(label='Advanced Popup Window', command=lambda: simple_popup_window())
popup_windows.add_command(label='Right Click Menu', command=lambda: rightclick_menu())
menubar.add_command(label="\u22EE")
###################################### S Y S T E M F U N C T I O N S ######################################
system_functions = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 System', menu=system_functions)
system_functions.add_command(label='Accelerator - menu item shortcut', accelerator="Ctrl+N",
command=lambda: statusbar.set("Menu Item Clicked"))
root.bind("<Control-n>", lambda event: statusbar.set("Shortcut Ctrl+N used to start a function"))
system_functions.add_command(label='Auto Repeat Functions', command=lambda: auto_repeat_function())
system_functions.add_command(label='Autopopulate with clickable labels', command=lambda: autopopulate(SAMPLE_LIST))
system_functions.add_command(label='Backup Database Auto', command=lambda: backup_database_auto())
system_functions.add_command(label='Backup Database Select', command=lambda: backup_database_select())
system_functions.add_command(label='Check Input Date', command=lambda: statusbar.set(f"{check_input_date('2020-01-01')}"))
system_functions.add_command(label='Check Input Time', command=lambda: statusbar.set(f"{check_input_time('15:15')}"))
system_functions.add_command(label='Check Input Email', command=lambda: statusbar.set(f"{check_input_email('lord.huriko@gmail.com')}"))
system_functions.add_command(label='Check Input Price', command=lambda: statusbar.set(f"{check_input_price('99.99')}"))
system_functions.add_command(label='Check If File Edited', command=lambda: check_if_file_edited())
system_functions.add_command(label='Children Clear All in Scroll Window', command=lambda: cscroll())
system_functions.add_command(label='Children Clear All in Selected Window', command=lambda: c(root))
system_functions.add_command(label='Children Edit All in a Window', command=lambda: edit_children())
system_functions.add_command(label='Children Find Widget by String ID', command=lambda: find_children())
system_functions.add_command(label='Children Read Text From Entries', command=lambda: read_from_text_children())
system_functions.add_command(label='Children Select Active Notebook Tab', command=lambda: select_active_child())
system_functions.add_command(label='Copy Label Text to Clipboard', command=lambda: copy_to_clipboard())
system_functions.add_command(label='Display Initial and Updated Root sizes', command=lambda: window_size())
system_functions.add_command(label='Display Window Size and Position', command=lambda: display_window_size_and_position())
system_functions.add_command(label='Dynamically resize Window', command=lambda: resize_window())
system_functions.add_command(label='Position Window in the Middle of the Screen', command=lambda: position())
system_functions.add_command(label='Remove Single Widget', command=lambda: remove_widget())
system_functions.add_command(label='Save Pickle', command=lambda: save_all())
system_functions.add_command(label='Scrollable Canvas Edit Settings', command=lambda: configure_scrollable_canvas())
system_functions.add_command(label='Threading', command=lambda: task_threading())
system_functions.add_command(label='Timestamp', command=lambda: statusbar.set(timestamp()))
menubar.add_command(label="\u22EE")
############################################### W I D G E T S ################################################
widgets = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label='📂 Widgets', menu=widgets)
widgets.add_command(label='Checkbutton', command=lambda: widget_checkbutton())
widgets.add_command(label='Combobox', command=lambda: widget_combobox())
widgets.add_command(label='Dropdown Box', command=lambda: widget_dropdown_box())
widgets.add_command(label='Entry as Password', command=lambda: entry_as_password())
widgets.add_command(label='Entry auto delete hint', command=lambda: entry_auto_delete())
widgets.add_command(label='LabelFrame', command=lambda: widget_labelframe())
widgets.add_command(label='Label Wrap Text', command=lambda: widget_label_wrap())
widgets.add_command(label='Listbox', command=lambda: widget_listbox())
widgets.add_command(label='Listbox advanced', command=lambda: widget_listbox_advanced_with_scrollbar())
widgets.add_command(label='Notebook', command=lambda: widget_notebook())
widgets.add_command(label='Paned (resizable) window', command=lambda: paned_window())
widgets.add_command(label='Progress Bar', command=lambda: widget_progress_bar())
widgets.add_command(label='Radiobutton', command=lambda: widget_radiobutton())
widgets.add_command(label='Scales', command=lambda: widget_scales())
widgets.add_command(label='Scrollbar', command=lambda: widget_scrollbar())
widgets.add_command(label='Spinbox', command=lambda: widget_spinbox())
widgets.add_command(label='Treeview', command=lambda: widget_treeview())
widgets.add_separator()
########################################################################################################################
################################################## S T Y L E S ###################################################
########################################################################################################################
style = ttk.Style(root)
# style.theme_use("clam") # 'winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative'
# Global style
style.configure("TNotebook.Tab", font=("Calibri", 10), padding=10) # every notebook will have this style
# Manual style
style.configure("MyStyle.TLabel", font=("Calibri", 20), padding=5) # add using style="MyStyle.TLabel"
import tkinter.font as tkFont
labels_font = tkFont.Font(size=9, weight="bold", underline=True) # add using font=labels_font
print(root.winfo_class())
########################################################################################################################
################################################# A U T O R U N ##################################################
########################################################################################################################
root.after(0, app_menu())
root.after(0, display_image())
########################################################################################################################
############################################### S T A T U S B A R ################################################
########################################################################################################################
statusbar = tk.StringVar()
ttk.Label(root, textvariable=statusbar, anchor='center').grid(row=1, column=0, sticky="EW")
########################################################################################################################
# Images required for Treeview Widget
picture_renatka = tk.PhotoImage(file="./assets/solutions/misia.png")
picture_krzysio = tk.PhotoImage(file="./assets/solutions/misio.png")
picture_both = tk.PhotoImage(file="./assets/solutions/house.png")
# Image required for Canvas with image background
# image_canvas = ImageTk.PhotoImage(file="./assets/solutions/pic01.png")
root.mainloop()