171 lines
6.2 KiB
Python
171 lines
6.2 KiB
Python
"""
|
||
GUI匹配编辑器模块
|
||
|
||
提供编辑文件匹配关系的图形界面。
|
||
"""
|
||
|
||
import os
|
||
import tkinter as tk
|
||
from tkinter import ttk, messagebox
|
||
|
||
|
||
def show_matching_editor(matched_pairs, images_root):
|
||
"""显示匹配编辑窗口,允许手动调整匹配关系"""
|
||
# 创建匹配编辑窗口
|
||
editor_window = tk.Toplevel()
|
||
editor_window.title('文件匹配编辑')
|
||
editor_window.geometry('900x600')
|
||
editor_window.transient()
|
||
editor_window.grab_set()
|
||
|
||
# 获取所有图片文件夹
|
||
all_image_folders = []
|
||
if os.path.isdir(images_root):
|
||
for root, dirs, _ in os.walk(images_root):
|
||
for dir_name in dirs:
|
||
folder_path = os.path.join(root, dir_name)
|
||
rel_path = os.path.relpath(folder_path, images_root)
|
||
all_image_folders.append((folder_path, rel_path))
|
||
|
||
# 标题
|
||
title_frame = ttk.Frame(editor_window)
|
||
title_frame.pack(fill='x', padx=10, pady=10)
|
||
ttk.Label(title_frame, text='文件匹配编辑', font=('', 14, 'bold')).pack()
|
||
ttk.Label(title_frame, text='选择要修改的项目,然后从右侧选择图片文件夹').pack()
|
||
|
||
# 主体区域(使用PanedWindow分割)
|
||
paned = ttk.PanedWindow(editor_window, orient='horizontal')
|
||
paned.pack(fill='both', expand=True, padx=10, pady=10)
|
||
|
||
# 左侧表格区域
|
||
left_frame = ttk.Frame(paned)
|
||
paned.add(left_frame, weight=2)
|
||
|
||
# 表格标题
|
||
ttk.Label(left_frame, text='TXT文件匹配列表:', font=('', 10, 'bold')).pack(anchor='w', pady=(0, 5))
|
||
|
||
# 表格区域
|
||
table_frame = ttk.Frame(left_frame)
|
||
table_frame.pack(fill='both', expand=True)
|
||
|
||
# 创建Treeview表格
|
||
columns = ('index', 'txt_name', 'image_folder')
|
||
tree = ttk.Treeview(table_frame, columns=columns, show='headings', height=15)
|
||
tree.heading('index', text='序号')
|
||
tree.heading('txt_name', text='TXT文件名')
|
||
tree.heading('image_folder', text='匹配的图片文件夹')
|
||
tree.column('index', width=60)
|
||
tree.column('txt_name', width=200)
|
||
tree.column('image_folder', width=250)
|
||
|
||
# 表格滚动条
|
||
table_scrollbar = ttk.Scrollbar(table_frame, orient='vertical', command=tree.yview)
|
||
tree.configure(yscrollcommand=table_scrollbar.set)
|
||
tree.pack(side='left', fill='both', expand=True)
|
||
table_scrollbar.pack(side='right', fill='y')
|
||
|
||
# 右侧文件夹列表区域
|
||
right_frame = ttk.Frame(paned)
|
||
paned.add(right_frame, weight=1)
|
||
|
||
# 文件夹列表标题
|
||
ttk.Label(right_frame, text='可用的图片文件夹:', font=('', 10, 'bold')).pack(anchor='w', pady=(0, 5))
|
||
|
||
# 文件夹列表区域
|
||
folders_frame = ttk.Frame(right_frame)
|
||
folders_frame.pack(fill='both', expand=True)
|
||
|
||
# 创建文件夹列表
|
||
folders_listbox = tk.Listbox(folders_frame, selectmode='single')
|
||
for folder_path, rel_path in all_image_folders:
|
||
folders_listbox.insert('end', rel_path)
|
||
|
||
# 文件夹列表滚动条
|
||
folders_scrollbar = ttk.Scrollbar(folders_frame, orient='vertical', command=folders_listbox.yview)
|
||
folders_listbox.configure(yscrollcommand=folders_scrollbar.set)
|
||
folders_listbox.pack(side='left', fill='both', expand=True)
|
||
folders_scrollbar.pack(side='right', fill='y')
|
||
|
||
# 操作按钮区域
|
||
button_frame = ttk.Frame(editor_window)
|
||
button_frame.pack(fill='x', padx=10, pady=10)
|
||
|
||
# 提供通过闭包访问变量的方式
|
||
selected_item_id = [None] # type: ignore
|
||
|
||
def on_tree_select(event):
|
||
"""TreeView选中事件"""
|
||
selection = tree.selection()
|
||
if selection:
|
||
selected_item_id[0] = selection[0] # type: ignore
|
||
|
||
tree.bind('<<TreeviewSelect>>', on_tree_select)
|
||
|
||
def set_matching():
|
||
"""设置选中项的匹配"""
|
||
if not selected_item_id[0]:
|
||
messagebox.showwarning('警告', '请先选择一个TXT文件')
|
||
return
|
||
|
||
folder_selection = folders_listbox.curselection()
|
||
if not folder_selection:
|
||
messagebox.showwarning('警告', '请先选择一个图片文件夹')
|
||
return
|
||
|
||
# 获取选中的索引
|
||
item_values = tree.item(selected_item_id[0], 'values')
|
||
row_index = int(item_values[0])
|
||
|
||
# 获取选中的文件夹
|
||
folder_index = folder_selection[0]
|
||
folder_path, folder_rel = all_image_folders[folder_index]
|
||
|
||
# 更新匹配关系
|
||
matched_pairs[row_index]['image_folder'] = {
|
||
"path": folder_path,
|
||
"name": os.path.basename(folder_path),
|
||
"relative_path": folder_rel
|
||
}
|
||
|
||
# 更新表格显示
|
||
tree.item(selected_item_id[0], values=(row_index, item_values[1], folder_rel))
|
||
|
||
messagebox.showinfo('成功', f'已将 "{item_values[1]}" 匹配到 "{folder_rel}"')
|
||
|
||
def clear_matching():
|
||
"""清除选中项的匹配"""
|
||
if not selected_item_id[0]:
|
||
messagebox.showwarning('警告', '请先选择一个TXT文件')
|
||
return
|
||
|
||
# 获取选中的索引
|
||
item_values = tree.item(selected_item_id[0], 'values')
|
||
row_index = int(item_values[0])
|
||
|
||
# 清除匹配关系
|
||
matched_pairs[row_index]['image_folder'] = None
|
||
|
||
# 更新表格显示
|
||
tree.item(selected_item_id[0], values=(row_index, item_values[1], '无匹配'))
|
||
|
||
messagebox.showinfo('成功', f'已清除 "{item_values[1]}" 的匹配关系')
|
||
|
||
def apply_all():
|
||
"""应用所有修改"""
|
||
editor_window.destroy()
|
||
|
||
# 按钮
|
||
ttk.Button(button_frame, text='设置选中项', command=set_matching).pack(side='left', padx=5)
|
||
ttk.Button(button_frame, text='清除选中项', command=clear_matching).pack(side='left', padx=5)
|
||
ttk.Button(button_frame, text='应用所有', command=apply_all).pack(side='right', padx=5)
|
||
|
||
# 填充表格数据
|
||
for i, pair in enumerate(matched_pairs):
|
||
txt_name = pair['txt']['name']
|
||
img_folder = pair['image_folder']['relative_path'] if pair['image_folder'] else '无匹配'
|
||
tree.insert('', 'end', values=(i, txt_name, img_folder))
|
||
|
||
# 等待窗口关闭
|
||
editor_window.wait_window()
|
||
|
||
return matched_pairs |