4 Commits

Author SHA1 Message Date
7a8ca677ea ♻️ Refactor generators and add an about window 2024-09-13 17:51:58 +02:00
Shikiryu
5112439712 🚧 Add Quickposes model download 2024-09-13 00:59:04 +02:00
5941da9ae5 Add cheated pause
For #36
2024-06-17 14:16:58 +02:00
a8c0979ef1 Add not cheated pause
For #36
2024-06-14 17:35:28 +02:00
8 changed files with 141 additions and 4 deletions

BIN
assets/icons/pause.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

BIN
assets/icons/sand-clock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

View File

@@ -4,3 +4,5 @@ pygame~=2.4.0
customtkinter~=5.1.3
configparser~=5.3.0
CTkToolTip~=0.4
requests~=2.32.3
CTkMenuBar~=0.8

View File

@@ -10,6 +10,7 @@ class ImagePlaceholder:
self.is_break = False
self.current_image = None
self.current_original_image = None
self.paused_original_image = None
self.image_window = image_window
self.images = images.copy()
@@ -61,3 +62,16 @@ class ImagePlaceholder:
self.image_label.configure(bg="#e8d4bc" if self.is_break else "#FFFFFF")
self.image_label.configure(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

@@ -3,6 +3,7 @@ import subprocess
import sys
from tkinter import *
from tkinter.ttk import Progressbar, Style
from tkinter.messagebox import *
import customtkinter
from CTkToolTip import *
@@ -14,6 +15,7 @@ from src.util import Util
class Toolbar:
def __init__(self, image_window, timer):
self.timers = []
self.is_paused = False
self.current_image = None
self.current_original_image = None
self.image_window = image_window
@@ -29,6 +31,11 @@ class Toolbar:
next_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(next_button, delay=0.1, message="Next", y_offset=-40, x_offset=-40)
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"
"-white.png")),
text="", command=self.toggle_black_white)
@@ -58,7 +65,7 @@ class Toolbar:
CTkToolTip(self.fullscreen_button, delay=0.1, message="Fullscreen", y_offset=-40, x_offset=-40)
timer_button = customtkinter.CTkButton(toolbar, command=self.toggle_timer, text="",
image=ImageTk.PhotoImage(Image.open("assets/icons/timer.png")))
image=ImageTk.PhotoImage(Image.open("assets/icons/sand-clock.png")))
timer_button.pack(side=LEFT, padx=0, pady=0)
CTkToolTip(timer_button, delay=0.1, message="Toggle timer", y_offset=-40, x_offset=-40)
@@ -147,3 +154,23 @@ class Toolbar:
"fullscreen"] else Util.get_default_button_color())
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)

41
src/entity/generator.py Normal file
View File

@@ -0,0 +1,41 @@
from datetime import datetime
import os
import io
import tempfile
import requests
from PIL import Image
class Generator(object):
def __init__(self, generator=None, folder=None):
self.selected_folder = folder
if generator == 'poses':
self.generate_poses()
def generate_poses(self):
dt = datetime.now()
ts = int(datetime.timestamp(dt))
url = 'https://quickposes.com/ajax/getPosesForSlider/Chiaroscuro?_=' + str(ts)
resp_json = requests.get(url=url)
if resp_json.status_code == 200:
data = resp_json.json()
c = 0
for src in data:
if os.path.exists(os.path.join(self.selected_folder, src['src'])):
continue
if c >= 3:
break
buffer = tempfile.SpooledTemporaryFile(max_size=1e9)
r = requests.get('https://quickposes.com/assets/poses/' + src['src'], stream=True)
if r.status_code == 200:
downloaded = 0
for chunk in r.iter_content(chunk_size=1024):
downloaded += len(chunk)
buffer.write(chunk)
buffer.seek(0)
i = Image.open(io.BytesIO(buffer.read()))
i.save(os.path.join(self.selected_folder, src['src']), quality=85)
buffer.close()
c += 1

30
src/window/about.py Normal file
View File

@@ -0,0 +1,30 @@
import webbrowser
import customtkinter
from customtkinter import CTkToplevel
class AboutWindow:
def __init__(self, app):
self.app = app
self.window = CTkToplevel(app.root)
self.window.title("À propos")
self.window.geometry("600x300")
self.window.protocol("WM_DELETE_WINDOW", self.on_closing)
link_gesture_drawing = customtkinter.CTkLabel(self.window, text="Open Source alternative to GestureDrawing!")
link_gesture_drawing.pack()
link_gesture_drawing.bind("<Button-1>",
lambda e: self.open_link("https://cubebrush.co/advanches/products/d9q6yq/gesturedrawing"))
link_shikiryu = customtkinter.CTkLabel(self.window, text="by Shikiryu")
link_shikiryu.pack()
link_shikiryu.bind("<Button-1>", lambda e: self.open_link("https://shikiryu.com"))
@staticmethod
def open_link(url):
webbrowser.open_new(url)
def on_closing(self):
self.window.destroy()

View File

@@ -4,9 +4,12 @@ from tkinter import *
from tkinter import filedialog
import customtkinter
from src.entity.config import Config
from src.entity.generator import Generator
from src.util import Util
from src.window.about import AboutWindow
from src.window.image import ImageWindow
from src.window.session import SessionWindow
from CTkMenuBar import *
class App:
@@ -22,6 +25,17 @@ class App:
self.selected_folder = ""
self.found_images = []
self.timer = 0
menu = CTkMenuBar(master=root)
generate_button = menu.add_cascade("Generate")
help_button = menu.add_cascade("Help")
dropdown = CustomDropdownMenu(widget=generate_button)
dropdown.add_option(option="Poses", command=lambda:self.download_poses('poses'))
about = CustomDropdownMenu(widget=help_button)
about.add_option(option="À propos", command=self.show_help)
self.title = customtkinter.CTkLabel(root, text="Drawing Training")
self.title.pack()
@@ -49,7 +63,8 @@ class App:
self.buttons = []
for i, timer in enumerate(timers):
new_button = customtkinter.CTkButton(self.button_frame, width=10, text=timer, command=lambda t=timer: self.set_timer_in_seconds(t))
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.append(new_button)
@@ -66,6 +81,9 @@ class App:
except Exception:
pass
def show_help(self):
AboutWindow(self)
def lets_draw(self):
self.image_window = ImageWindow(self)
self.image_window.lets_draw(self.found_images.copy(), self.timer)
@@ -83,6 +101,10 @@ class App:
self.find_images_in_folder()
self.check_lets_draw()
def download_poses(self, generator=None):
Generator(generator=generator, folder=self.selected_folder)
self.find_images_in_folder()
def find_images_in_folder(self):
if Path(self.selected_folder).exists():
self.found_images = list(
@@ -99,7 +121,8 @@ class App:
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()))
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
if user_data == "Custom":