py一个文件夹图片浏览和删除脚本

AI生成内容
image_browser.py

import os
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import configparser
# pip install Pillow
class ImageBrowser:
    def __init__(self, root):
        self.root = root
        self.root.title("图片浏览器")
        
        # 配置文件路径
        self.config_file = "image_browser_config.ini"
        
        # 图片列表和当前索引
        self.image_list = []
        self.current_index = 0
        self.current_image_path = None
        self.current_directory = ""
        
        # 创建界面
        self.create_widgets()
        
        # 绑定快捷键
        self.root.bind('<Left>', lambda e: self.previous_image())
        self.root.bind('<Right>', lambda e: self.next_image())
        self.root.bind('<Up>', lambda e: self.previous_image())
        self.root.bind('<Down>', lambda e: self.next_image())
        self.root.bind('<Delete>', lambda e: self.delete_image())
        self.root.bind('d', lambda e: self.delete_image())
        self.root.bind('D', lambda e: self.delete_image())
        
        # 加载上次的状态
        self.load_config()
        
        # 如果有保存的目录,自动加载
        if self.current_directory:
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, self.current_directory)
            self.load_images()
        else:
            # 默认设置为当前目录
            # current_dir = os.getcwd()
            current_dir = os.path.join(os.getcwd(), "images")
            self.dir_entry.insert(0, current_dir)
            self.current_directory = current_dir
        
    def create_widgets(self):
        # 目录选择区域
        dir_frame = tk.Frame(self.root)
        dir_frame.pack(pady=10, padx=10, fill=tk.X)
        
        self.dir_entry = tk.Entry(dir_frame, width=50)
        self.dir_entry.pack(side=tk.LEFT, padx=5)
        
        browse_btn = tk.Button(dir_frame, text="浏览目录", command=self.browse_directory)
        browse_btn.pack(side=tk.LEFT, padx=5)
        
        load_btn = tk.Button(dir_frame, text="加载图片", command=self.load_images)
        load_btn.pack(side=tk.LEFT, padx=5)
        
        # 图片显示区域
        self.image_label = tk.Label(self.root, text="请选择目录并加载图片", bg="gray", width=100, height=45)
        self.image_label.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)
        
        # 按钮区域
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=10)
        
        prev_btn = tk.Button(btn_frame, text="上一张 (←/↑)", command=self.previous_image)
        prev_btn.pack(side=tk.LEFT, padx=10)
        
        next_btn = tk.Button(btn_frame, text="下一张 (→/↓)", command=self.next_image)
        next_btn.pack(side=tk.LEFT, padx=10)
        
        delete_btn = tk.Button(btn_frame, text="删除 (Delete/d)", command=self.delete_image, bg="#ff6b6b")
        delete_btn.pack(side=tk.LEFT, padx=10)
        
        # 状态栏
        self.status_label = tk.Label(self.root, text="", relief=tk.SUNKEN, anchor=tk.W)
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
        
    def browse_directory(self):
        current_directory = self.current_directory
        if not os.path.exists(current_directory):
            current_directory = os.getcwd()
        directory = filedialog.askdirectory(initialdir=current_directory)
        if directory:
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, directory)

            self.load_images()
    
    def load_config(self):
        """从配置文件加载上次的状态"""
        try:
            if os.path.exists(self.config_file):
                config = configparser.ConfigParser()
                config.read(self.config_file, encoding='utf-8')
                
                if 'Settings' in config:
                    self.current_directory = config['Settings'].get('directory', '')
                    saved_index = config['Settings'].get('index', '0')
                    self.current_index = int(saved_index)
        except Exception as e:
            print(f"加载配置文件失败: {e}")
    
    def save_config(self):
        """保存当前状态到配置文件"""
        try:
            config = configparser.ConfigParser()
            config['Settings'] = {
                'directory': self.current_directory,
                'index': str(self.current_index)
            }
            with open(self.config_file, 'w', encoding='utf-8') as f:
                config.write(f)
        except Exception as e:
            print(f"保存配置文件失败: {e}")
    
    def load_images(self):
        directory = self.dir_entry.get().strip()
        
        if not directory:
            messagebox.showwarning("警告", "请输入或选择目录")
            return
        
        if not os.path.isdir(directory):
            messagebox.showerror("错误", "目录不存在")
            return
        
        # 保存当前目录
        self.current_directory = directory
        
        # 支持的图片格式
        image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff'}
        
        self.image_list = []
        for filename in os.listdir(directory):
            file_ext = os.path.splitext(filename)[1].lower()  # 获取扩展名并转为小写
            if file_ext in image_extensions:
                full_path = os.path.join(directory, filename)
                self.image_list.append(full_path)
        
        if not self.image_list:
            messagebox.showinfo("提示", "该目录下没有找到图片")
            return
        
        # 排序
        self.image_list.sort()
        
        # 验证索引是否有效
        if self.current_index >= len(self.image_list):
            self.current_index = 0
        
        # 显示图片
        self.display_image()
        self.update_status()
        self.save_config()
    
    def display_image(self):
        if not self.image_list:
            self.image_label.config(image='', text="没有图片")
            return
        
        # 确保索引在有效范围内
        if self.current_index >= len(self.image_list):
            self.current_index = len(self.image_list) - 1
        
        if self.current_index < 0:
            self.current_index = 0
        
        # 尝试读取图片,如果失败则跳过到下一张
        max_attempts = len(self.image_list)
        attempts = 0
        pil_img = None
        
        while attempts < max_attempts:
            self.current_image_path = self.image_list[self.current_index]
            
            # 使用PIL读取图片
            try:
                pil_img = Image.open(self.current_image_path)
                break
            except Exception as e:
                # 无法读取图片,跳过
                print(f"无法读取图片: {self.current_image_path}, 错误: {e}")
                attempts += 1
                
                # 移动到下一张
                self.current_index += 1
                if self.current_index >= len(self.image_list):
                    self.current_index = 0
        
        if attempts >= max_attempts or pil_img is None:
            messagebox.showerror("错误", "无法读取任何图片")
            self.image_label.config(image='', text="无法读取图片")
            return
        
        # 转换为RGB模式(如果需要)
        if pil_img.mode != 'RGB':
            pil_img = pil_img.convert('RGB')
        
        # 调整图片大小以适应窗口
        w, h = pil_img.size
        max_width = 1100
        max_height = 750
        
        if w > max_width or h > max_height:
            scale = min(max_width / w, max_height / h)
            new_w = int(w * scale)
            new_h = int(h * scale)
            pil_img = pil_img.resize((new_w, new_h), Image.LANCZOS)
        
        # 创建PhotoImage
        photo = ImageTk.PhotoImage(pil_img)
        
        # 显示图片
        self.image_label.config(image=photo, text="")
        self.image_label.image = photo
        
        # 更新窗口标题
        self.root.title(f"图片浏览器 - {os.path.basename(self.current_image_path)} ({self.current_index + 1}/{len(self.image_list)})")
        
        # 保存配置
        self.save_config()
    
    def previous_image(self):
        if not self.image_list:
            return
        
        self.current_index -= 1
        if self.current_index < 0:
            self.current_index = 0
            self.root.title(f"图片浏览器 - {os.path.basename(self.current_image_path)} ({self.current_index + 1}/{len(self.image_list)})")
            messagebox.showinfo("提示", "已经是第一张图片")
            return
        
        self.display_image()
        self.update_status()
    
    def next_image(self):
        if not self.image_list:
            return
        
        self.current_index += 1
        if self.current_index >= len(self.image_list):
            self.current_index = 0  # 循环到第一张
            self.root.title(f"图片浏览器 - {os.path.basename(self.current_image_path)} ({self.current_index + 1}/{len(self.image_list)})")
            messagebox.showinfo("提示", "已回到第一张图片")
            return
        
        self.display_image()
        self.update_status()
    
    def delete_image(self):
        if not self.image_list:
            return
        
        if not self.current_image_path:
            return
        
        try:
            os.remove(self.current_image_path)
            self.image_list.pop(self.current_index)
            
            # 删除后保持当前索引不变,会自动指向下一张
            # 如果删除的是最后一张,索引会自动调整
            if self.current_index >= len(self.image_list) and len(self.image_list) > 0:
                self.current_index = len(self.image_list) - 1
            
            if self.image_list:
                self.display_image()
            else:
                self.image_label.config(image='', text="没有图片")
                self.current_image_path = None
            
            self.update_status()
            self.save_config()
            
        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def update_status(self):
        if self.image_list:
            status = f"当前: {os.path.basename(self.current_image_path)} | 索引: {self.current_index + 1}/{len(self.image_list)}"
        else:
            status = "没有图片"
        
        self.status_label.config(text=status)

def create_icon():
    """创建图标文件"""
    try:
        from PIL import Image, ImageDraw
        
        # 图标尺寸
        sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
        
        # 创建不同尺寸的图标
        images = []
        for size in sizes:
            # 创建图像
            img = Image.new('RGBA', size, (0, 0, 0, 0))
            draw = ImageDraw.Draw(img)
            
            # 绘制背景圆角矩形
            margin = size[0] // 8
            draw.rounded_rectangle(
                [margin, margin, size[0] - margin, size[1] - margin],
                radius=size[0] // 4,
                fill=(70, 130, 180, 255)  # 钢蓝色
            )
            
            # 绘制图片图标(简单的矩形框)
            img_margin = size[0] // 4
            img_size = size[0] - 2 * img_margin
            draw.rectangle(
                [img_margin, img_margin, img_margin + img_size, img_margin + img_size],
                outline=(255, 255, 255, 255),
                width=max(1, size[0] // 32)
            )
            
            # 绘制简单的"山"形(代表图片)
            mountain_margin = size[0] // 3
            mountain_top = size[1] - size[1] // 3
            mountain_bottom = size[1] - size[1] // 6
            
            # 左边的山
            draw.polygon([
                (mountain_margin, mountain_bottom),
                (mountain_margin + img_size // 3, mountain_margin + img_size // 4),
                (mountain_margin + img_size // 2, mountain_bottom)
            ], fill=(255, 255, 255, 200))
            
            # 右边的山
            draw.polygon([
                (mountain_margin + img_size // 2, mountain_bottom),
                (mountain_margin + img_size * 2 // 3, mountain_margin + img_size // 3),
                (mountain_margin + img_size, mountain_bottom)
            ], fill=(255, 255, 255, 200))
            
            # 太阳
            sun_radius = size[0] // 16
            sun_center = (mountain_margin + img_size // 8, mountain_margin + img_size // 8)
            draw.ellipse(
                [sun_center[0] - sun_radius, sun_center[1] - sun_radius,
                 sun_center[0] + sun_radius, sun_center[1] + sun_radius],
                fill=(255, 200, 100, 255)
            )
            
            images.append(img)
        return images
        
        
    except ImportError:
        print("警告: 未安装PIL库,无法创建图标")
        print("将使用默认图标")
        return None
    except Exception as e:
        print(f"创建图标失败: {e}")
        print("将使用默认图标")
        return None

def main():
    root = tk.Tk()
    img=create_icon()
    photo = ImageTk.PhotoImage(img[1])  
    root.iconphoto(True, photo)# 设置图标
    root.geometry("1200x900")
    
    # 设置窗口图标
    try:
        if os.path.exists('icon.ico'):
            root.iconbitmap('icon.ico')
    except Exception as e:
        print(f"设置图标失败: {e}")
    
    app = ImageBrowser(root)
    root.mainloop()

if __name__ == "__main__":
    main()


打包脚本 pyinstaller --name=ImageBrowser --onefile --windowed --icon=icon.ico --clean --noconfirm image_browser.py

"""
打包脚本 - 使用PyInstaller将image_browser.py打包为exe
"""

import os
import sys
import subprocess

def create_icon():
    """创建图标文件"""
    try:
        from PIL import Image, ImageDraw
        
        # 图标尺寸
        sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
        
        # 创建不同尺寸的图标
        images = []
        for size in sizes:
            # 创建图像
            img = Image.new('RGBA', size, (0, 0, 0, 0))
            draw = ImageDraw.Draw(img)
            
            # 绘制背景圆角矩形
            margin = size[0] // 8
            draw.rounded_rectangle(
                [margin, margin, size[0] - margin, size[1] - margin],
                radius=size[0] // 4,
                fill=(70, 130, 180, 255)  # 钢蓝色
            )
            
            # 绘制图片图标(简单的矩形框)
            img_margin = size[0] // 4
            img_size = size[0] - 2 * img_margin
            draw.rectangle(
                [img_margin, img_margin, img_margin + img_size, img_margin + img_size],
                outline=(255, 255, 255, 255),
                width=max(1, size[0] // 32)
            )
            
            # 绘制简单的"山"形(代表图片)
            mountain_margin = size[0] // 3
            mountain_top = size[1] - size[1] // 3
            mountain_bottom = size[1] - size[1] // 6
            
            # 左边的山
            draw.polygon([
                (mountain_margin, mountain_bottom),
                (mountain_margin + img_size // 3, mountain_margin + img_size // 4),
                (mountain_margin + img_size // 2, mountain_bottom)
            ], fill=(255, 255, 255, 200))
            
            # 右边的山
            draw.polygon([
                (mountain_margin + img_size // 2, mountain_bottom),
                (mountain_margin + img_size * 2 // 3, mountain_margin + img_size // 3),
                (mountain_margin + img_size, mountain_bottom)
            ], fill=(255, 255, 255, 200))
            
            # 太阳
            sun_radius = size[0] // 16
            sun_center = (mountain_margin + img_size // 8, mountain_margin + img_size // 8)
            draw.ellipse(
                [sun_center[0] - sun_radius, sun_center[1] - sun_radius,
                 sun_center[0] + sun_radius, sun_center[1] + sun_radius],
                fill=(255, 200, 100, 255)
            )
            
            images.append(img)
        
        # 保存为ICO文件
        icon_path = "icon.ico"
        images[0].save(
            icon_path,
            format='ICO',
            sizes=[(img.width, img.height) for img in images]
        )
        
        print(f"图标已创建: {icon_path}")
        return icon_path
        
    except ImportError:
        print("警告: 未安装PIL库,无法创建图标")
        print("将使用默认图标")
        return None
    except Exception as e:
        print(f"创建图标失败: {e}")
        print("将使用默认图标")
        return None

def build_exe():
    """打包为exe文件"""
    
    # 创建图标
    print("步骤 1/3: 创建图标...")
    icon_path = create_icon()
    if icon_path:
        print(f"✓ 图标创建成功\n")
    else:
        print("✓ 使用默认图标\n")
    
    # PyInstaller命令
    print("步骤 2/3: 开始打包...")
    cmd = [
        'pyinstaller',
        '--name=ImageBrowser',
        '--onefile',
        '--windowed',
    ]
    
    # 如果图标创建成功,添加图标参数
    if icon_path and os.path.exists(icon_path):
        cmd.append(f'--icon={icon_path}')
    else:
        cmd.append('--icon=NONE')
    
    cmd.extend([
        '--clean',
        '--noconfirm',
        'image_browser.py'
    ])
    
    print(f"命令: {' '.join(cmd)}\n")
    
    try:
        # 执行打包命令
        result = subprocess.run(cmd, check=True, capture_output=True, text=True)
        print("✓ 打包成功!")
        print(result.stdout)
        
        # 检查生成的exe文件
        exe_path = os.path.join('dist', 'ImageBrowser.exe')
        if os.path.exists(exe_path):
            file_size = os.path.getsize(exe_path) / (1024 * 1024)  # MB
            print(f"\n步骤 3/3: 验证生成的文件")
            print(f"✓ EXE文件: {exe_path}")
            print(f"✓ 文件大小: {file_size:.2f} MB")
        else:
            print("\n警告: 未找到生成的exe文件")
            
    except subprocess.CalledProcessError as e:
        print("✗ 打包失败!")
        print(f"错误信息: {e.stderr}")
        sys.exit(1)
    except FileNotFoundError:
        print("✗ 错误: 未找到pyinstaller命令")
        print("请先安装PyInstaller: pip install pyinstaller")
        sys.exit(1)

if __name__ == "__main__":
    print("=" * 50)
    print("       图片浏览器 - EXE打包工具")
    print("=" * 50)
    print()
    build_exe()
    print()
    print("=" * 50)
    print("       打包完成!")
    print("=" * 50)




一个改进版本

import os
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import configparser

class ImageBrowser:
    def __init__(self, root):
        self.root = root
        self.root.title("图片浏览器")
        
        # 配置文件路径
        self.config_file = "image_browser_config.ini"
        
        # 图片列表和当前索引
        self.image_list = []
        self.current_index = 0
        self.current_image_path = None
        self.current_directory = ""
        
        # 图片显示相关
        self.original_image = None  # 原始图片
        self.displayed_image = None  # 显示的图片
        self.scale_factor = 1.0  # 缩放因子
        self.offset_x = 0  # X偏移
        self.offset_y = 0  # Y偏移
        self.drag_start_x = 0  # 拖动起始X
        self.drag_start_y = 0  # 拖动起始Y
        
        # 创建界面
        self.create_widgets()
        
        # 绑定快捷键
        self.root.bind('<Left>', lambda e: self.previous_image())
        self.root.bind('<Right>', lambda e: self.next_image())
        self.root.bind('<Up>', lambda e: self.previous_image())
        self.root.bind('<Down>', lambda e: self.next_image())
        self.root.bind('<Delete>', lambda e: self.delete_image())
        self.root.bind('d', lambda e: self.delete_image())
        self.root.bind('D', lambda e: self.delete_image())
        
        # 加载上次的状态
        self.load_config()
        
        # 如果有保存的目录,自动加载
        if self.current_directory:
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, self.current_directory)
            self.load_images()
        else:
            # 默认设置为当前目录
            current_dir = os.path.join(os.getcwd(), "images")
            self.dir_entry.insert(0, current_dir)
            self.current_directory = current_dir
    
    def create_widgets(self):
        # 目录选择区域
        dir_frame = tk.Frame(self.root)
        dir_frame.pack(pady=10, padx=10, fill=tk.X)
        
        self.dir_entry = tk.Entry(dir_frame, width=50)
        self.dir_entry.pack(side=tk.LEFT, padx=5)
        
        browse_btn = tk.Button(dir_frame, text="浏览目录", command=self.browse_directory)
        browse_btn.pack(side=tk.LEFT, padx=5)
        
        load_btn = tk.Button(dir_frame, text="加载图片", command=self.load_images)
        load_btn.pack(side=tk.LEFT, padx=5)
        
        # 图片显示区域(使用Canvas支持滚动和拖动)
        self.canvas_frame = tk.Frame(self.root)
        self.canvas_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)
        
        self.canvas = tk.Canvas(self.canvas_frame, bg="gray")
        self.canvas.pack(fill=tk.BOTH, expand=True)
        
        # 绑定鼠标事件
        self.canvas.bind('<MouseWheel>', self.on_mouse_wheel)  # Windows
        self.canvas.bind('<Button-4>', self.on_mouse_wheel)  # Linux scroll up
        self.canvas.bind('<Button-5>', self.on_mouse_wheel)  # Linux scroll down
        self.canvas.bind('<ButtonPress-1>', self.on_mouse_press)  # 鼠标按下
        self.canvas.bind('<B1-Motion>', self.on_mouse_drag)  # 鼠标拖动
        self.canvas.bind('<ButtonRelease-1>', self.on_mouse_release)  # 鼠标释放
        
        # 按钮区域
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=10)
        
        prev_btn = tk.Button(btn_frame, text="上一张 (←/↑)", command=self.previous_image)
        prev_btn.pack(side=tk.LEFT, padx=10)
        
        next_btn = tk.Button(btn_frame, text="下一张 (→/↓)", command=self.next_image)
        next_btn.pack(side=tk.LEFT, padx=10)
        
        delete_btn = tk.Button(btn_frame, text="删除 (Delete/d)", command=self.delete_image, bg="#ff6b6b")
        delete_btn.pack(side=tk.LEFT, padx=10)
        
        # 状态栏
        self.status_label = tk.Label(self.root, text="", relief=tk.SUNKEN, anchor=tk.W)
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X)
    
    def on_mouse_wheel(self, event):
        """鼠标滚轮缩放"""
        if not self.original_image:
            return
        
        # 确定缩放方向
        if event.num == 5 or event.delta < 0:
            # 向下滚动,缩小
            new_scale = self.scale_factor * 0.9
        else:
            # 向上滚动,放大
            new_scale = self.scale_factor * 1.1
        
        # 限制缩放范围
        if new_scale < 0.1:
            new_scale = 0.1
        elif new_scale > 10.0:
            new_scale = 10.0
        
        # 计算缩放中心(鼠标位置)
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        mouse_x = event.x
        mouse_y = event.y
        
        # 计算缩放前的图片中心相对于鼠标的位置
        old_image_x = mouse_x - self.offset_x
        old_image_y = mouse_y - self.offset_y
        
        # 更新缩放因子
        self.scale_factor = new_scale
        
        # 计算新的偏移量,使缩放中心保持在鼠标位置
        self.offset_x = mouse_x - old_image_x * (new_scale / self.scale_factor)
        self.offset_y = mouse_y - old_image_y * (new_scale / self.scale_factor)
        
        # 重新显示图片
        self.display_scaled_image()
    
    def on_mouse_press(self, event):
        """鼠标按下"""
        self.drag_start_x = event.x
        self.drag_start_y = event.y
    
    def on_mouse_drag(self, event):
        """鼠标拖动"""
        if not self.original_image:
            return
        
        # 计算拖动距离
        dx = event.x - self.drag_start_x
        dy = event.y - self.drag_start_y
        
        # 更新偏移量
        self.offset_x += dx
        self.offset_y += dy
        
        # 更新起始位置
        self.drag_start_x = event.x
        self.drag_start_y = event.y
        
        # 重新显示图片
        self.display_scaled_image()
    
    def on_mouse_release(self, event):
        """鼠标释放"""
        pass
    
    def browse_directory(self):
        current_directory = self.current_directory
        if not os.path.exists(current_directory):
            current_directory = os.getcwd()
        directory = filedialog.askdirectory(initialdir=current_directory)
        if directory:
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, directory)
            self.load_images()
    
    def load_config(self):
        """从配置文件加载上次的状态"""
        try:
            if os.path.exists(self.config_file):
                config = configparser.ConfigParser()
                config.read(self.config_file, encoding='utf-8')
                
                if 'Settings' in config:
                    self.current_directory = config['Settings'].get('directory', '')
                    saved_index = config['Settings'].get('index', '0')
                    self.current_index = int(saved_index)
        except Exception as e:
            print(f"加载配置文件失败: {e}")
    
    def save_config(self):
        """保存当前状态到配置文件"""
        try:
            config = configparser.ConfigParser()
            config['Settings'] = {
                'directory': self.current_directory,
                'index': str(self.current_index)
            }
            with open(self.config_file, 'w', encoding='utf-8') as f:
                config.write(f)
        except Exception as e:
            print(f"保存配置文件失败: {e}")
    
    def load_images(self):
        directory = self.dir_entry.get().strip()
        
        if not directory:
            messagebox.showwarning("警告", "请输入或选择目录")
            return
        
        if not os.path.isdir(directory):
            messagebox.showerror("错误", "目录不存在")
            return
        
        # 保存当前目录
        self.current_directory = directory
        
        # 支持的图片格式
        image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff'}
        
        self.image_list = []
        for filename in os.listdir(directory):
            file_ext = os.path.splitext(filename)[1].lower()
            if file_ext in image_extensions:
                full_path = os.path.join(directory, filename)
                self.image_list.append(full_path)
        
        if not self.image_list:
            messagebox.showinfo("提示", "该目录下没有找到图片")
            return
        
        # 排序
        self.image_list.sort()
        
        # 验证索引是否有效
        if self.current_index >= len(self.image_list):
            self.current_index = 0
        
        # 显示图片
        self.display_image()
        self.update_status()
        self.save_config()
    
    def display_image(self):
        if not self.image_list:
            self.canvas.delete("all")
            self.canvas.create_text(400, 300, text="没有图片", fill="white", font=("Arial", 20))
            return
        
        # 确保索引在有效范围内
        if self.current_index >= len(self.image_list):
            self.current_index = len(self.image_list) - 1
        
        if self.current_index < 0:
            self.current_index = 0
        
        # 尝试读取图片,如果失败则跳过到下一张
        max_attempts = len(self.image_list)
        attempts = 0
        
        while attempts < max_attempts:
            self.current_image_path = self.image_list[self.current_index]
            
            # 使用PIL读取图片
            try:
                self.original_image = Image.open(self.current_image_path)
                break
            except Exception as e:
                # 无法读取图片,跳过
                print(f"无法读取图片: {self.current_image_path}, 错误: {e}")
                attempts += 1
                
                # 移动到下一张
                self.current_index += 1
                if self.current_index >= len(self.image_list):
                    self.current_index = 0
        
        if attempts >= max_attempts:
            messagebox.showerror("错误", "无法读取任何图片")
            self.canvas.delete("all")
            self.canvas.create_text(400, 300, text="无法读取图片", fill="white", font=("Arial", 20))
            return
        
        # 转换为RGB模式(如果需要)
        if self.original_image.mode != 'RGB':
            self.original_image = self.original_image.convert('RGB')
        
        # 重置偏移
        self.offset_x = 0
        self.offset_y = 0
        
        # 获取画布尺寸
        self.root.update()  # 确保窗口已更新
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        
        # 如果画布尺寸为0(窗口未完全初始化),使用默认值
        if canvas_width <= 1:
            canvas_width = 1100
        if canvas_height <= 1:
            canvas_height = 750
        
        # 计算图片原始尺寸
        img_width, img_height = self.original_image.size
        
        # 如果图片尺寸超过画布,自动缩放以适应画布
        if img_width > canvas_width or img_height > canvas_height:
            scale_width = canvas_width / img_width
            scale_height = canvas_height / img_height
            self.scale_factor = min(scale_width, scale_height)  # 使用较小的缩放比例
            # 留一点边距
            self.scale_factor *= 0.95
        else:
            self.scale_factor = 1.0
        
        # 显示图片
        self.display_scaled_image()
        
        # 更新窗口标题
        self.root.title(f"图片浏览器 - {os.path.basename(self.current_image_path)} ({self.current_index + 1}/{len(self.image_list)})")
        
        # 保存配置
        self.save_config()
    
    def display_scaled_image(self):
        """显示缩放后的图片"""
        if not self.original_image:
            return
        
        # 计算缩放后的尺寸
        w, h = self.original_image.size
        new_w = int(w * self.scale_factor)
        new_h = int(h * self.scale_factor)
        
        # 缩放图片
        if self.scale_factor != 1.0:
            scaled_image = self.original_image.resize((new_w, new_h), Image.LANCZOS)
        else:
            scaled_image = self.original_image
        
        # 转换为PhotoImage
        self.displayed_image = ImageTk.PhotoImage(scaled_image)
        
        # 清除画布
        self.canvas.delete("all")
        
        # 获取画布尺寸
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        
        # 如果画布尺寸为0(窗口未完全初始化),使用默认值
        if canvas_width <= 1:
            canvas_width = 1100
        if canvas_height <= 1:
            canvas_height = 750
        
        # 计算居中位置(如果没有拖动偏移)
        if self.offset_x == 0 and self.offset_y == 0:
            center_x = canvas_width // 2
            center_y = canvas_height // 2
            self.canvas.create_image(
                center_x, center_y,
                anchor=tk.CENTER,
                image=self.displayed_image
            )
        else:
            # 使用拖动偏移
            self.canvas.create_image(
                self.offset_x, self.offset_y,
                anchor=tk.NW,
                image=self.displayed_image
            )
    
    def previous_image(self):
        if not self.image_list:
            return
        
        self.current_index -= 1
        if self.current_index < 0:
            self.current_index = 0
            self.root.title(f"图片浏览器 - {os.path.basename(self.current_image_path)} ({self.current_index + 1}/{len(self.image_list)})")
            messagebox.showinfo("提示", "已经是第一张图片")
            return
        
        self.display_image()
        self.update_status()
    
    def next_image(self):
        if not self.image_list:
            return
        
        self.current_index += 1
        if self.current_index >= len(self.image_list):
            self.current_index = 0  # 循环到第一张
            self.root.title(f"图片浏览器 - {os.path.basename(self.current_image_path)} ({self.current_index + 1}/{len(self.image_list)})")
            messagebox.showinfo("提示", "已回到第一张图片")
            return
        
        self.display_image()
        self.update_status()
    
    def delete_image(self):
        if not self.image_list:
            return
        
        if not self.current_image_path:
            return
        
        try:
            os.remove(self.current_image_path)
            self.image_list.pop(self.current_index)
            
            # 删除后保持当前索引不变,会自动指向下一张
            # 如果删除的是最后一张,索引会自动调整
            if self.current_index >= len(self.image_list) and len(self.image_list) > 0:
                self.current_index = len(self.image_list) - 1
            
            if self.image_list:
                self.display_image()
            else:
                self.canvas.delete("all")
                self.canvas.create_text(400, 300, text="没有图片", fill="white", font=("Arial", 20))
                self.current_image_path = None
            
            self.update_status()
            self.save_config()
            
        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def update_status(self):
        if self.image_list:
            status = f"当前: {os.path.basename(self.current_image_path)} | 索引: {self.current_index + 1}/{len(self.image_list)} | 缩放: {self.scale_factor:.1f}x"
        else:
            status = "没有图片"
        
        self.status_label.config(text=status)

def create_icon():
    """创建图标文件"""
    try:
        from PIL import Image, ImageDraw
        
        # 图标尺寸
        sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
        
        # 创建不同尺寸的图标
        images = []
        for size in sizes:
            # 创建图像
            img = Image.new('RGBA', size, (0, 0, 0, 0))
            draw = ImageDraw.Draw(img)
            
            # 绘制背景圆角矩形
            margin = size[0] // 8
            draw.rounded_rectangle(
                [margin, margin, size[0] - margin, size[1] - margin],
                radius=size[0] // 4,
                fill=(70, 130, 180, 255)  # 钢蓝色
            )
            
            # 绘制图片图标(简单的矩形框)
            img_margin = size[0] // 4
            img_size = size[0] - 2 * img_margin
            draw.rectangle(
                [img_margin, img_margin, img_margin + img_size, img_margin + img_size],
                outline=(255, 255, 255, 255),
                width=max(1, size[0] // 32)
            )
            
            # 绘制简单的"山"形(代表图片)
            mountain_margin = size[0] // 3
            mountain_top = size[1] - size[1] // 3
            mountain_bottom = size[1] - size[1] // 6
            
            # 左边的山
            draw.polygon([
                (mountain_margin, mountain_bottom),
                (mountain_margin + img_size // 3, mountain_margin + img_size // 4),
                (mountain_margin + img_size // 2, mountain_bottom)
            ], fill=(255, 255, 255, 200))
            
            # 右边的山
            draw.polygon([
                (mountain_margin + img_size // 2, mountain_bottom),
                (mountain_margin + img_size * 2 // 3, mountain_margin + img_size // 3),
                (mountain_margin + img_size, mountain_bottom)
            ], fill=(255, 255, 255, 200))
            
            # 太阳
            sun_radius = size[0] // 16
            sun_center = (mountain_margin + img_size // 8, mountain_margin + img_size // 8)
            draw.ellipse(
                [sun_center[0] - sun_radius, sun_center[1] - sun_radius,
                 sun_center[0] + sun_radius, sun_center[1] + sun_radius],
                fill=(255, 200, 100, 255)
            )
            
            images.append(img)
        
        # # 保存为ICO文件
        # icon_path = "icon.ico"
        # images[0].save(
        #     icon_path,
        #     format='ICO',
        #     sizes=[(img.width, img.height) for img in images]
        # )
        
        # print(f"图标已创建: {icon_path}")
        return images
        
    except ImportError:
        print("警告: 未安装PIL库,无法创建图标")
        print("将使用默认图标")
        return None
    except Exception as e:
        print(f"创建图标失败: {e}")
        print("将使用默认图标")
        return None

def main():
    root = tk.Tk()
    root.geometry("1200x900")
    
    # 设置窗口图标
    try:
        images = create_icon()
        if images:
            photo = ImageTk.PhotoImage(images[1])
            root.iconphoto(True, photo)
    except Exception as e:
        print(f"设置图标失败: {e}")
    
    app = ImageBrowser(root)
    root.mainloop()

if __name__ == "__main__":
    main()

posted @ 2026-04-16 15:02  小城熊儿  阅读(5)  评论(0)    收藏  举报