Compare commits

..

1 Commits

Author SHA1 Message Date
d99478935d 🚧 Add icons in toolbar
For #17
2023-06-15 12:12:52 +02:00
12 changed files with 34 additions and 132 deletions

View File

@ -1,19 +0,0 @@
# Drawing Training
Open Source alternative to [GestureDrawing!](https://cubebrush.co/advanches/products/d9q6yq/gesturedrawing)
## Authors
- [@shikiryu](https://git.shikiryu.com/Shikiryu)
## Installation
Install my-project with python
```bash
sudo apt install cmake build-essential tcl-dev tk-dev python3-tk
pip install -r requirements.txt
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

View File

@ -1,6 +1,5 @@
import os import os
import sys import sys
from tkinter import PhotoImage
import customtkinter import customtkinter
@ -16,9 +15,7 @@ def main():
root = customtkinter.CTk() root = customtkinter.CTk()
root.title("Drawing Training!") root.title("Drawing Training!")
root.geometry("300x300") root.geometry("300x600")
icon = PhotoImage(file="assets/icons/logo-dt.png")
root.iconphoto(True, icon)
App(root) App(root)

View File

@ -1,20 +1,12 @@
.PHONY: build dist .PHONY: build dist
.ONESHELL: TOTAL_LOCATION := $(pip show customtkinter | grep Location)
VENV_DIR=.venv LOCATION=!TOTAL_LOCATION:~0,10!
ACTIVATE_VENV:=. $(VENV_DIR)/bin/activate
LOCATION:= $(shell pip show customtkinter | grep Location | cut -c 11-)
install:
python3 -m venv "$(VENV_DIR)"
$(ACTIVATE_VENV)
pip install --upgrade --requirement requirements.txt
build_linux: build_linux:
rm -rf build dist drawingtraining.spec rm -rf build dist drawingtraining.spec
$(ACTIVATE_VENV)
pyinstaller main.py --onefile -w --hidden-import="PIL._tkinter_finder" -n drawingtraining --add-data "assets:assets" pyinstaller main.py --onefile -w --hidden-import="PIL._tkinter_finder" -n drawingtraining --add-data "assets:assets"
build_windows: build_windows:
rm -rf build dist drawingtraining.spec rm -rf build dist drawingtraining.spec
pyinstaller main.py --onefile -w --hidden-import="PIL._tkinter_finder" -n drawingtraining --add-data "assets;assets" --add-data "$(LOCATION)\customtkinter;customtkinter" --icon="assets/icons/logo-dt.png" pyinstaller main.py --onefile -w --hidden-import="PIL._tkinter_finder" -n drawingtraining --add-data "assets;assets" --add-data "${LOCATION}\customtkinter;customtkinter\"

View File

@ -1,5 +1,5 @@
pillow~=10.0.1 pillow~=9.5.0
pyinstaller==5.13.1 pyinstaller==5.12.0
pygame~=2.4.0 pygame~=2.4.0
customtkinter~=5.1.3 customtkinter~=5.1.3
configparser~=5.3.0 configparser~=5.3.0

View File

@ -1,7 +1,5 @@
import copy import copy
from tkinter import * from tkinter import *
import PIL
from PIL import ImageTk, Image, ImageOps from PIL import ImageTk, Image, ImageOps
@ -10,7 +8,6 @@ class ImagePlaceholder:
self.is_break = False self.is_break = False
self.current_image = None self.current_image = None
self.current_original_image = None self.current_original_image = None
self.paused_original_image = None
self.image_window = image_window self.image_window = image_window
self.images = images.copy() self.images = images.copy()
@ -19,9 +16,6 @@ class ImagePlaceholder:
self.image_label.pack(side=TOP, fill=BOTH, expand=1) self.image_label.pack(side=TOP, fill=BOTH, expand=1)
def display_new_image(self): def display_new_image(self):
if len(self.images) == 0:
self.image_window.on_closing()
return
image_path = self.images.pop(0) image_path = self.images.pop(0)
if image_path == "break": if image_path == "break":
self.is_break = True self.is_break = True
@ -41,7 +35,7 @@ class ImagePlaceholder:
if w < 21 or h < 21: if w < 21 or h < 21:
w = 1280 w = 1280
h = 1024 h = 1024
self.current_image.thumbnail((w - 20, h - 20), PIL.Image.Resampling.LANCZOS) self.current_image.thumbnail((w - 20, h - 20), Image.ANTIALIAS)
if reload: if reload:
self.load_widget() self.load_widget()
@ -62,16 +56,3 @@ class ImagePlaceholder:
self.image_label.configure(bg="#e8d4bc" if self.is_break else "#FFFFFF") self.image_label.configure(bg="#e8d4bc" if self.is_break else "#FFFFFF")
self.image_label.configure(image=image_to_display) self.image_label.configure(image=image_to_display)
self.image_label.image = image_to_display self.image_label.image = image_to_display
def pause(self, pause=True, cheat=False):
if pause:
self.paused_original_image = self.current_original_image
if not cheat:
image_path = 'assets/images/break.jpg'
self.current_original_image = Image.open(image_path)
else:
self.current_original_image = self.paused_original_image
self.paused_original_image = None
self.current_image = copy.deepcopy(self.current_original_image)
self.apply_options()

View File

@ -1,21 +1,18 @@
import copy
import os import os
import subprocess import subprocess
import sys import sys
from tkinter import * from tkinter import *
from tkinter.ttk import Progressbar, Style
from tkinter.messagebox import *
import customtkinter
from CTkToolTip import * from CTkToolTip import *
from PIL import ImageTk, Image from PIL import ImageTk, Image, ImageOps
import customtkinter
from src.util import Util from src.util import Util
class Toolbar: class Toolbar:
def __init__(self, image_window, timer): def __init__(self, image_window, timer):
self.timers = [] self.timers = []
self.is_paused = False
self.current_image = None self.current_image = None
self.current_original_image = None self.current_original_image = None
self.image_window = image_window self.image_window = image_window
@ -29,67 +26,52 @@ class Toolbar:
next_button = customtkinter.CTkButton(toolbar, image=ImageTk.PhotoImage(Image.open("assets/icons/next.png")), next_button = customtkinter.CTkButton(toolbar, image=ImageTk.PhotoImage(Image.open("assets/icons/next.png")),
text="", command=self.image_window.next_image) text="", command=self.image_window.next_image)
next_button.pack(side=LEFT, padx=0, pady=0) next_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(next_button, delay=0.1, message="Next", y_offset=-40, x_offset=-40) CTkToolTip(next_button, delay=0.5, message="Next")
pause_button = customtkinter.CTkButton(toolbar, image=ImageTk.PhotoImage(Image.open("assets/icons/pause.png")),
text="", command=self.pause)
pause_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(pause_button, delay=0.1, message="Next", y_offset=-40, x_offset=-40)
self.bw_button = customtkinter.CTkButton(toolbar, image=ImageTk.PhotoImage(Image.open("assets/icons/black-and" self.bw_button = customtkinter.CTkButton(toolbar, image=ImageTk.PhotoImage(Image.open("assets/icons/black-and"
"-white.png")), "-white.png")),
text="", command=self.toggle_black_white) text="", command=self.toggle_black_white)
self.bw_button.pack(side=LEFT, padx=0, pady=0) self.bw_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(self.bw_button, delay=0.1, message="Black and white image", y_offset=-40, x_offset=-40) CTkToolTip(self.bw_button, delay=0.5, message="Black and white image")
self.mirror_button = customtkinter.CTkButton(toolbar, command=self.toggle_mirror, text="", self.mirror_button = customtkinter.CTkButton(toolbar, command=self.toggle_mirror, text="",
image=ImageTk.PhotoImage(Image.open("assets/icons/flip.png"))) image=ImageTk.PhotoImage(Image.open("assets/icons/flip.png")))
self.mirror_button.pack(side=LEFT, padx=0, pady=0) self.mirror_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(self.mirror_button, delay=0.1, message="Mirrored image", y_offset=-40, x_offset=-40) CTkToolTip(self.mirror_button, delay=0.5, message="Mirrored image")
open_folder_button = customtkinter.CTkButton(toolbar, command=self.open_folder, text="", open_folder_button = customtkinter.CTkButton(toolbar, command=self.open_folder, text="",
image=ImageTk.PhotoImage(Image.open("assets/icons/folder.png"))) image=ImageTk.PhotoImage(Image.open("assets/icons/folder.png")))
open_folder_button.pack(side=LEFT, padx=0, pady=0) open_folder_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(open_folder_button, delay=0.1, message="Open folder", y_offset=-40, x_offset=-40) CTkToolTip(open_folder_button, delay=0.5, message="Open folder")
self.always_on_top_button = customtkinter.CTkButton(toolbar, command=self.toggle_always_on_top, text="", self.always_on_top_button = customtkinter.CTkButton(toolbar, command=self.toggle_always_on_top, text="",
image=ImageTk.PhotoImage( image=ImageTk.PhotoImage(
Image.open("assets/icons/copy.png"))) Image.open("assets/icons/copy.png")))
self.always_on_top_button.pack(side=LEFT, padx=0, pady=0) self.always_on_top_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(self.always_on_top_button, delay=0.1, message="Always on top", y_offset=-40, x_offset=-40) CTkToolTip(self.always_on_top_button, delay=0.5, message="Always on top")
self.fullscreen_button = customtkinter.CTkButton(toolbar, command=self.toggle_fullscreen, text="", self.fullscreen_button = customtkinter.CTkButton(toolbar, command=self.toggle_fullscreen, text="",
image=ImageTk.PhotoImage( image=ImageTk.PhotoImage(
Image.open("assets/icons/maximize.png"))) Image.open("assets/icons/maximize.png")))
self.fullscreen_button.pack(side=LEFT, padx=0, pady=0) self.fullscreen_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(self.fullscreen_button, delay=0.1, message="Fullscreen", y_offset=-40, x_offset=-40) CTkToolTip(self.fullscreen_button, delay=0.5, message="Fullscreen")
timer_button = customtkinter.CTkButton(toolbar, command=self.toggle_timer, text="", timer_button = customtkinter.CTkButton(toolbar, command=self.toggle_timer, text="",
image=ImageTk.PhotoImage(Image.open("assets/icons/sand-clock.png"))) image=ImageTk.PhotoImage(Image.open("assets/icons/timer.png")))
timer_button.pack(side=LEFT, padx=0, pady=0) timer_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(timer_button, delay=0.1, message="Toggle timer", y_offset=-40, x_offset=-40) CTkToolTip(timer_button, delay=0.5, message="Toggle timer")
self.timer_label = customtkinter.CTkLabel(toolbar, text=str(self.timer), self.timer_label = customtkinter.CTkLabel(toolbar, text=str(self.timer),
text_color=Util.get_default_button_color()) text_color=Util.get_default_button_color())
self.timer_label.pack(side=RIGHT, ipadx=20) self.timer_label.pack(side=RIGHT, ipadx=20)
style = Style()
style.theme_use('default')
style.configure("black.Horizontal.TProgressbar", background='black')
self.progressbar = Progressbar(toolbar, length=280)
self.progressbar.pack(side=RIGHT, ipadx=20)
def display_new_timer(self): def display_new_timer(self):
if len(self.timers) == 0:
return
self.timer = self.timers.pop(0) self.timer = self.timers.pop(0)
self.timer_label.configure(text=Util.format_seconds(self.timer)) self.timer_label.configure(text=Util.format_seconds(self.timer))
self.timer_check = self.image_window.window.after(1000, self.update_timer, self.timer) self.timer_check = self.image_window.window.after(1000, self.update_timer, self.timer)
def update_timer(self, current): def update_timer(self, current):
current -= 1 current -= 1
self.progressbar['value'] = 100 - (current * 100 / self.timer)
if current == 10: if current == 10:
self.image_window.play_countdown() self.image_window.play_countdown()
if current > 0: if current > 0:
@ -121,11 +103,8 @@ class Toolbar:
try: try:
self.timer_label.pack_info() self.timer_label.pack_info()
self.timer_label.pack_forget() self.timer_label.pack_forget()
self.progressbar.pack_info()
self.progressbar.pack_forget()
except TclError: except TclError:
self.timer_label.pack(side=RIGHT, ipadx=20) self.timer_label.pack(side=RIGHT, ipadx=20)
self.progressbar.pack(side=RIGHT, ipadx=20)
def open_folder(self): def open_folder(self):
if sys.platform == "win32": if sys.platform == "win32":
@ -154,23 +133,3 @@ class Toolbar:
"fullscreen"] else Util.get_default_button_color()) "fullscreen"] else Util.get_default_button_color())
self.image_window.window.attributes("-fullscreen", self.image_window.option["fullscreen"]) self.image_window.window.attributes("-fullscreen", self.image_window.option["fullscreen"])
def pause(self):
cheating = False
if not self.is_paused:
cheating = askyesno("Pause", "Laisser l'image affichée ?")
self.is_paused = True
else:
self.is_paused = False
# timer is paused whatever happened
if self.timer_check is not None:
self.image_window.window.after_cancel(self.timer_check)
self.timer_check = None
else:
self.timer_check = self.image_window.window.after(
1000, self.update_timer, int((100-self.progressbar['value'])*self.timer/100)
)
self.image_window.image.pause(pause=self.is_paused, cheat=cheating)

View File

@ -47,4 +47,4 @@ class Util:
@staticmethod @staticmethod
def get_default_active_button_color(): def get_default_active_button_color():
return "green", "green" return "gray29", "gray29"

View File

@ -1,4 +1,3 @@
import tkinter
from pathlib import Path from pathlib import Path
from tkinter import * from tkinter import *
from tkinter import filedialog from tkinter import filedialog
@ -34,8 +33,8 @@ class App:
self.images_len = customtkinter.CTkLabel(root, text="Found : " + str(len(self.found_images))) self.images_len = customtkinter.CTkLabel(root, text="Found : " + str(len(self.found_images)))
self.images_len.pack() self.images_len.pack()
self.button_frame = Frame(root, bg=root.cget("bg")) self.button_frame = Frame(root)
self.button_frame.pack(fill=X, expand=True) self.button_frame.pack(fill=X)
timers = [ timers = [
Util.format_seconds(30), Util.format_seconds(30),
@ -46,15 +45,14 @@ class App:
Util.format_seconds(600), Util.format_seconds(600),
"Custom" "Custom"
] ]
self.buttons = customtkinter.CTkSegmentedButton(
self.buttons = [] root, values=timers,
for i, timer in enumerate(timers): command=self.set_timer_in_seconds
new_button = customtkinter.CTkButton(self.button_frame, width=10, text=timer, command=lambda t=timer: self.set_timer_in_seconds(t)) )
new_button.pack(side=tkinter.LEFT, fill=X, expand=True) self.buttons.pack(fill=X)
self.buttons.append(new_button)
self.launch_button = customtkinter.CTkButton(root, text="Let's draw!", command=self.lets_draw, state="disabled") self.launch_button = customtkinter.CTkButton(root, text="Let's draw!", command=self.lets_draw, state="disabled")
self.launch_button.pack(side=tkinter.BOTTOM) self.launch_button.pack(side="bottom")
self.read_config() self.read_config()
@ -75,13 +73,11 @@ class App:
self.session_window.open() self.session_window.open()
def select_folder(self): def select_folder(self):
new_directory = filedialog.askdirectory() self.selected_folder = filedialog.askdirectory()
if new_directory: self.folder_name.configure(text="Folder : " + self.selected_folder)
self.selected_folder = new_directory Config.set_config_var("default_folder", self.selected_folder).save()
self.folder_name.configure(text="Folder : " + self.selected_folder) self.find_images_in_folder()
Config.set_config_var("default_folder", self.selected_folder).save() self.check_lets_draw()
self.find_images_in_folder()
self.check_lets_draw()
def find_images_in_folder(self): def find_images_in_folder(self):
if Path(self.selected_folder).exists(): if Path(self.selected_folder).exists():
@ -97,10 +93,6 @@ class App:
self.launch_button.configure(state="disabled") self.launch_button.configure(state="disabled")
def set_timer_in_seconds(self, user_data): def set_timer_in_seconds(self, user_data):
# resetting buttons states
for button in self.buttons:
button.configure(fg_color=(Util.get_default_button_color() if user_data != button.cget("text") else Util.get_default_active_button_color()))
self.custom = False self.custom = False
if user_data == "Custom": if user_data == "Custom":
return self.custom_session() return self.custom_session()

View File

@ -45,14 +45,14 @@ class SessionWindow:
text=session.number_of_drawings + " drawings of " + Util.format_seconds(int(session.timer)) + " each", text=session.number_of_drawings + " drawings of " + Util.format_seconds(int(session.timer)) + " each",
command=partial(self.edit_element, i), command=partial(self.edit_element, i),
fg_color=( fg_color=(
Util.get_default_active_button_color() if i == self.selected_element_index else Util.get_default_button_color()) Util.get_default_button_color() if i == self.selected_element_index else Util.get_default_active_button_color())
) )
elif isinstance(session, BreakElement): elif isinstance(session, BreakElement):
new_session = CTkButton(self.left_column, new_session = CTkButton(self.left_column,
text="Break of " + Util.format_seconds(int(session.timer)) + " each", text="Break of " + Util.format_seconds(int(session.timer)) + " each",
command=partial(self.edit_element, i), command=partial(self.edit_element, i),
fg_color=( fg_color=(
Util.get_default_active_button_color() if i == self.selected_element_index else Util.get_default_button_color()) Util.get_default_button_color() if i == self.selected_element_index else Util.get_default_active_button_color())
) )
else: else:
raise Exception("unknown type.") raise Exception("unknown type.")