Files
playwrite/gui/widgets/file_selector.py
Misaka_Company 71621dc8a0 feat: add Tkinter GUI application for ERP automation tools
Implement a comprehensive GUI application with the following features:
- Data Extraction tab: Extract material plan data from ERP system
- Material Validation tab: Validate material status and match deletions
- Data Query tab: Query database for production order information
- Settings tab: Manage ERP, database, browser, and path configurations

Key components:
- MainWindow: Tabbed interface with status bar
- ConfigManager: JSON-based configuration management
- LogText: Custom read-only text widget with colored logging
- FileSelector: Reusable file/directory selection component
- ProgressDialog: Modal progress dialog for long operations

Technical details:
- Thread-safe UI updates using root.after()
- Stdout capture for legacy script integration
- Event-based readonly mode allowing copy/select operations
- Custom widget composition to avoid Tkinter ScrolledText issues

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 13:33:23 +08:00

97 lines
2.7 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
文件选择器组件
提供文件/目录选择功能的组合组件。
"""
import tkinter as tk
from tkinter import filedialog, ttk
from typing import Optional, Callable
class FileSelector(ttk.Frame):
"""文件选择器组件"""
def __init__(
self,
parent,
label_text: str = "",
file_type: str = "file",
file_types: list = None,
initial_dir: str = "",
on_change: Optional[Callable] = None
):
"""
初始化文件选择器
Args:
parent: 父容器
label_text: 标签文本
file_type: 选择类型 ('file''directory')
file_types: 文件类型过滤器,如 [("Excel", "*.xlsx")]
initial_dir: 初始目录
on_change: 值改变时的回调函数
"""
super().__init__(parent)
self.file_type = file_type
self.file_types = file_types or [("所有文件", "*.*")]
self.initial_dir = initial_dir
self.on_change = on_change
# 创建标签
if label_text:
self.label = ttk.Label(self, text=label_text)
self.label.grid(row=0, column=0, sticky="w", padx=(0, 5))
# 创建输入框
self.entry_var = tk.StringVar()
self.entry = ttk.Entry(self, textvariable=self.entry_var, width=50)
self.entry.grid(row=0, column=1, sticky="ew", padx=5)
# 创建浏览按钮
self.browse_button = ttk.Button(self, text="浏览...", command=self._browse)
self.browse_button.grid(row=0, column=2, padx=5)
# 配置列权重
self.columnconfigure(1, weight=1)
def _browse(self) -> None:
"""打开文件/目录选择对话框"""
current_path = self.entry_var.get() or self.initial_dir
if self.file_type == "file":
path = filedialog.askopenfilename(
title="选择文件",
initialdir=current_path,
filetypes=self.file_types
)
else: # directory
path = filedialog.askdirectory(
title="选择目录",
initialdir=current_path
)
if path:
self.entry_var.set(path)
if self.on_change:
self.on_change(path)
def get(self) -> str:
"""获取当前选择的路径"""
return self.entry_var.get()
def set(self, path: str) -> None:
"""设置路径"""
self.entry_var.set(path)
def clear(self) -> None:
"""清空路径"""
self.entry_var.set("")
def is_empty(self) -> bool:
"""检查是否为空"""
return not self.entry_var.get()