90 lines
3 KiB
Python
90 lines
3 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import tkinter as tk
|
|
from PIL import Image, ImageTk
|
|
import screeninfo, sys, os
|
|
|
|
def show_image(image_path, max_width=400, max_height=300, hover_header=None, click_url=None):
|
|
root = tk.Tk()
|
|
root.overrideredirect(True)
|
|
root.withdraw()
|
|
root.after(100, root.deiconify)
|
|
root.attributes("-topmost", True)
|
|
root.attributes("-alpha", 0.85)
|
|
|
|
img = Image.open(image_path)
|
|
|
|
img_ratio = img.width / img.height
|
|
box_ratio = max_width / max_height
|
|
|
|
if img.width > max_width or img.height > max_height:
|
|
if img_ratio > box_ratio:
|
|
new_width = max_width
|
|
new_height = int(max_width / img_ratio)
|
|
else:
|
|
new_height = max_height
|
|
new_width = int(max_height * img_ratio)
|
|
try:
|
|
resample = Image.Resampling.LANCZOS
|
|
except AttributeError:
|
|
resample = Image.ANTIALIAS
|
|
img = img.resize((new_width, new_height), resample)
|
|
|
|
img_tk = ImageTk.PhotoImage(img)
|
|
img_width, img_height = img.size
|
|
|
|
monitors = screeninfo.get_monitors()
|
|
primary_screen = next((m for m in monitors if m.is_primary), monitors[0])
|
|
|
|
screen_x = primary_screen.x
|
|
screen_y = primary_screen.y
|
|
screen_width = primary_screen.width
|
|
screen_height = primary_screen.height
|
|
|
|
x_pos = screen_x + screen_width - img_width - 20
|
|
y_pos = screen_y + screen_height - img_height - 60
|
|
|
|
root.geometry(f"{img_width}x{img_height}+{x_pos}+{y_pos}")
|
|
|
|
label = tk.Label(root, image=img_tk, borderwidth=0)
|
|
label.image = img_tk
|
|
label.pack()
|
|
|
|
header_label = tk.Label(root, text=hover_header, bg="black", fg="white", font=("Arial", 10))
|
|
header_visible = [False]
|
|
|
|
def update_hover_state():
|
|
x, y = root.winfo_pointerx() - root.winfo_rootx(), root.winfo_pointery() - root.winfo_rooty()
|
|
inside_label = 0 <= x <= img_width and 0 <= y <= img_height
|
|
inside_header = header_label.winfo_ismapped() and header_label.winfo_containing(x + root.winfo_rootx(), y + root.winfo_rooty()) is not None
|
|
|
|
if hover_header and (inside_label or inside_header):
|
|
if not header_visible[0]:
|
|
header_label.place(relx=0.5, rely=0, anchor="n", relwidth=1)
|
|
header_visible[0] = True
|
|
else:
|
|
if header_visible[0]:
|
|
header_label.place_forget()
|
|
header_visible[0] = False
|
|
|
|
root.after(100, update_hover_state)
|
|
|
|
def close_window(event=None):
|
|
root.destroy()
|
|
|
|
root.bind("<Button-1>", close_window if click_url is None else lambda e: os.system(f"xdg-open {click_url}"))
|
|
|
|
update_hover_state()
|
|
root.after(5000, close_window)
|
|
root.mainloop()
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) < 2:
|
|
print("Usage: show_image.py <image_path> [hover_header] [click_url]")
|
|
sys.exit(1)
|
|
|
|
image_path = sys.argv[1]
|
|
hover_header = sys.argv[2] if len(sys.argv) > 2 else None
|
|
click_url = sys.argv[3] if len(sys.argv) > 3 else None
|
|
|
|
show_image(image_path, hover_header=hover_header, click_url=click_url)
|