import os import random from tkinter import * from pygame import mixer from PIL import ImageTk, Image, ImageOps from util import Util class ImageWindow: def __init__(self, app): self.app = app self.window = Toplevel(app.root) self.window.title("Image") self.window.geometry("1280x1024") self.option = { "bw": False, "mirror": False, "always_on_top": False, } mixer.init() self.countdown_sound = mixer.Sound('assets/sounds/countdown.mp3') self.images = [] self.current_image = None self.image_label = None toolbar = Frame(self.window, bd=1, relief=RAISED) toolbar.pack(side=BOTTOM, fill=X) self.timer = 0 self.timer_label = None self.timer_check = None self.timer_check = None next_button = Button(toolbar, relief=FLAT, compound=LEFT, text="next ➡️", command=self.next_image) next_button.pack(side=LEFT, padx=0, pady=0) self.bw_button = Button(toolbar, relief=FLAT, compound=LEFT, text="black&white", command=self.toggle_black_white) self.bw_button.pack(side=LEFT, padx=0, pady=0) self.mirror_button = Button(toolbar, relief=FLAT, compound=LEFT, command=self.toggle_mirror, text="mirror") self.mirror_button.pack(side=LEFT, padx=0, pady=0) self.open_folder_button = Button(toolbar, relief=FLAT, compound=LEFT, command=self.open_folder , text="open folder") self.open_folder_button.pack(side=LEFT, padx=0, pady=0) self.always_on_top_button = Button(toolbar, relief=FLAT, compound=LEFT, command=self.toggle_always_on_top , text="always on top") self.always_on_top_button.pack(side=LEFT, padx=0, pady=0) self.always_on_top_check = None self.timer_button = Button(toolbar, relief=FLAT, compound=LEFT, command=self.toggle_timer, text="timer") self.timer_button.pack(side=LEFT, padx=0, pady=0) self.image_label = Label(self.window) self.image_label.pack(side=TOP, fill=BOTH, expand=1) self.timer_label = Label(toolbar, text=self.timer) self.timer_label.pack(side=RIGHT, ipadx=20) def update_timer(self, current): current -= 1 if current == 10: self.play_countdown() if current > 0: self.timer_label.configure(text=Util.format_seconds(current)) self.timer_check = self.window.after(1000, self.update_timer, current) else: self.window.after_cancel(self.timer_check) if len(self.images) == 0: self.window.destroy() self.window.update() return self.next_image() def next_image(self): if self.timer_check is not None: self.window.after_cancel(self.timer_check) self.display_new_image() self.display_new_timer() def toggle_black_white(self): self.option["bw"] = not self.option["bw"] self.bw_button.config(bg="blue" if self.option["bw"] else "grey85") def toggle_mirror(self): self.option["mirror"] = not self.option["mirror"] self.mirror_button.config(bg="blue" if self.option["mirror"] else "grey85") def toggle_timer(self): try: self.timer_label.pack_info() self.timer_label.pack_forget() except TclError: self.timer_label.pack(side=RIGHT, ipadx=20) def open_folder(self): os.startfile(self.app.selected_folder) def toggle_always_on_top(self): self.option["always_on_top"] = not self.option["always_on_top"] if self.option["always_on_top"]: self.always_on_top_button.config(bg="blue") self.stay_on_top() else: self.always_on_top_button.config(bg="grey85") self.window.after_cancel(self.always_on_top_check) def stay_on_top(self): # self.window.lift() self.window.attributes('-topmost', True) self.always_on_top_check = self.window.after(2000, self.stay_on_top) def lets_draw(self, images, timer): random.shuffle(images) self.images = images self.timer = timer self.next_image() def display_new_timer(self): self.timer_label.configure(text=self.timer) self.timer_check = self.window.after(1000, self.update_timer, self.timer) def display_new_image(self): image_path = self.images[0] self.images.pop(0) self.current_image = Image.open(image_path) self.resize_image() if self.option["bw"]: self.current_image = self.current_image.convert("L") if self.option["mirror"]: self.current_image = ImageOps.mirror(self.current_image) image_to_display = ImageTk.PhotoImage(self.current_image) self.image_label.configure(image=image_to_display) self.image_label.bind('', lambda event: self.resize_image()) self.image_label.image = image_to_display def resize_image(self): ma = self.window.winfo_toplevel() w, h = ma.winfo_width(), ma.winfo_height() # if self.current_image.size[0] > w or self.current_image.size[1] > h: if w < 21 or h < 21: # too small w = 1280 h = 1024 self.current_image.thumbnail((w - 20, h - 20), Image.ANTIALIAS) print("resized: win %s >= img %s", (w, h), self.current_image.size) image_to_display = ImageTk.PhotoImage(self.current_image) self.image_label.configure(image=image_to_display) self.image_label.image = image_to_display def play_countdown(self): self.countdown_sound.play()