Refactor PhotoTagger GUI to enhance image display and layout. Update canvas background color to match the theme, improve image resizing logic for better aspect ratio handling, and adjust grid configurations for match frames to ensure proper alignment and responsiveness. This enhances overall user experience and visual consistency across the interface.
This commit is contained in:
parent
360fcb0881
commit
15b7c10056
@ -1141,10 +1141,14 @@ class PhotoTagger:
|
||||
# Image display (left panel)
|
||||
image_frame = ttk.Frame(left_panel)
|
||||
image_frame.grid(row=0, column=0, pady=(0, 10), sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
image_frame.columnconfigure(0, weight=1)
|
||||
image_frame.rowconfigure(0, weight=1)
|
||||
|
||||
# Create canvas for image display
|
||||
canvas = tk.Canvas(image_frame, width=400, height=400, bg='white')
|
||||
canvas.grid(row=0, column=0)
|
||||
style = ttk.Style()
|
||||
canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
canvas = tk.Canvas(image_frame, width=400, height=400, bg=canvas_bg_color, highlightthickness=0)
|
||||
canvas.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# Input section (left panel)
|
||||
input_frame = ttk.LabelFrame(left_panel, text="Person Identification", padding="10")
|
||||
@ -1718,7 +1722,9 @@ class PhotoTagger:
|
||||
clear_all_btn.config(state='disabled')
|
||||
|
||||
# Create canvas for similar faces with scrollbar
|
||||
similar_canvas = tk.Canvas(similar_faces_frame, bg='white')
|
||||
style = ttk.Style()
|
||||
canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
similar_canvas = tk.Canvas(similar_faces_frame, bg=canvas_bg_color, highlightthickness=0)
|
||||
similar_scrollbar = ttk.Scrollbar(similar_faces_frame, orient="vertical", command=similar_canvas.yview)
|
||||
similar_scrollable_frame = ttk.Frame(similar_canvas)
|
||||
|
||||
@ -2171,12 +2177,43 @@ class PhotoTagger:
|
||||
try:
|
||||
# Load and display the face crop image
|
||||
pil_image = Image.open(face_crop_path)
|
||||
# Resize image to fit in window (max 400x400)
|
||||
pil_image.thumbnail((400, 400), Image.Resampling.LANCZOS)
|
||||
|
||||
# Get canvas dimensions
|
||||
canvas_width = canvas.winfo_width()
|
||||
canvas_height = canvas.winfo_height()
|
||||
|
||||
# If canvas hasn't been rendered yet, force update and use actual size
|
||||
if canvas_width <= 1 or canvas_height <= 1:
|
||||
# Force the canvas to update its geometry
|
||||
canvas.update_idletasks()
|
||||
canvas_width = canvas.winfo_width()
|
||||
canvas_height = canvas.winfo_height()
|
||||
|
||||
# If still not rendered, use default size
|
||||
if canvas_width <= 1:
|
||||
canvas_width = 400
|
||||
if canvas_height <= 1:
|
||||
canvas_height = 400
|
||||
|
||||
# Calculate scaling to fit within the canvas while maintaining aspect ratio
|
||||
img_width, img_height = pil_image.size
|
||||
scale_x = canvas_width / img_width
|
||||
scale_y = canvas_height / img_height
|
||||
# Allow slight upscaling (up to 1.2x) for better visibility, but cap to avoid excessive blurriness
|
||||
max_scale = min(1.2, max(scale_x, scale_y))
|
||||
scale = min(scale_x, scale_y, max_scale)
|
||||
|
||||
# Resize image to fill canvas
|
||||
new_width = int(img_width * scale)
|
||||
new_height = int(img_height * scale)
|
||||
pil_image = pil_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
||||
|
||||
photo = ImageTk.PhotoImage(pil_image)
|
||||
|
||||
# Update canvas
|
||||
canvas.create_image(200, 200, image=photo)
|
||||
# Center the image in the canvas
|
||||
x = canvas_width // 2
|
||||
y = canvas_height // 2
|
||||
canvas.create_image(x, y, image=photo)
|
||||
|
||||
# Keep a reference to prevent garbage collection
|
||||
canvas.image = photo
|
||||
@ -2592,20 +2629,21 @@ class PhotoTagger:
|
||||
# Bind the callback to the variable
|
||||
match_var.trace('w', make_callback(match_var, current_face_id, similar_face_id))
|
||||
|
||||
# Create a frame for the checkbox and text labels
|
||||
text_frame = ttk.Frame(match_frame)
|
||||
text_frame.pack(side=tk.LEFT, padx=(0, 10))
|
||||
# Configure match frame for grid layout
|
||||
match_frame.columnconfigure(0, weight=0) # Checkbox column - fixed width
|
||||
match_frame.columnconfigure(1, weight=1) # Text column - expandable
|
||||
match_frame.columnconfigure(2, weight=0) # Image column - fixed width
|
||||
|
||||
# Checkbox without text
|
||||
checkbox = ttk.Checkbutton(text_frame, variable=match_var)
|
||||
checkbox.pack(side=tk.LEFT, padx=(0, 5))
|
||||
checkbox = ttk.Checkbutton(match_frame, variable=match_var)
|
||||
checkbox.grid(row=0, column=0, rowspan=2, sticky=(tk.W, tk.N), padx=(0, 5))
|
||||
|
||||
# Create labels for confidence and filename
|
||||
confidence_label = ttk.Label(text_frame, text=f"{confidence_pct:.1f}% {confidence_desc}", font=("Arial", 9, "bold"))
|
||||
confidence_label.pack(anchor=tk.W)
|
||||
confidence_label = ttk.Label(match_frame, text=f"{confidence_pct:.1f}% {confidence_desc}", font=("Arial", 9, "bold"))
|
||||
confidence_label.grid(row=0, column=1, sticky=tk.W, padx=(0, 10))
|
||||
|
||||
filename_label = ttk.Label(text_frame, text=f"📁 {filename}", font=("Arial", 8), foreground="gray")
|
||||
filename_label.pack(anchor=tk.W)
|
||||
filename_label = ttk.Label(match_frame, text=f"📁 {filename}", font=("Arial", 8), foreground="gray")
|
||||
filename_label.grid(row=1, column=1, sticky=tk.W, padx=(0, 10))
|
||||
|
||||
# Face image (reusing auto-match image display)
|
||||
try:
|
||||
@ -2632,8 +2670,10 @@ class PhotoTagger:
|
||||
face_crops.append(face_crop_path)
|
||||
|
||||
# Create canvas for face image (like in auto-match)
|
||||
match_canvas = tk.Canvas(match_frame, width=80, height=80, bg='white')
|
||||
match_canvas.pack(side=tk.LEFT, padx=(10, 0))
|
||||
style = ttk.Style()
|
||||
canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
match_canvas = tk.Canvas(match_frame, width=80, height=80, bg=canvas_bg_color, highlightthickness=0)
|
||||
match_canvas.grid(row=0, column=2, rowspan=2, sticky=(tk.W, tk.N), padx=(10, 0))
|
||||
|
||||
# Load and display image (reusing auto-match image loading)
|
||||
pil_image = Image.open(face_crop_path)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user