当前位置: 首页 > news >正文

win10程序(十四)pdf转docx简易版

‘’‘

这是一个使用Python和Tkinter开发的PDF转DOCX转换工具,具有美观的糖果色界面和批量转换功能。

## 功能特点

- 批量选择和转换PDF文件
- 糖果色主题的友好界面
- 实时转换进度显示
- 详细的转换日志记录
- 简单易用的操作方式

’‘’

# -*- coding: utf-8 -*-

import tkinter as tk

from tkinter import filedialog, messagebox, ttk

import os

import threading

import time

import sys

# 检查依赖项

try:

    from pdf2docx import Converter

    DEPENDENCY_AVAILABLE = True

except ImportError:

    DEPENDENCY_AVAILABLE = False

    print("警告: 未找到pdf2docx模块,请运行 'pip install pdf2docx' 来安装")

class PDFtoDOCXConverter:

    def __init__(self, root):

        self.root = root

        self.root.title("PDF转DOCX转换器")

        self.root.geometry("1000x600")  # 调整窗口大小以适应内容

        self.root.resizable(True, True)  # 允许调整窗口大小

       

        # 设置糖果色主题

        self.colors = {

            'primary': '#FF6B6B',    # 珊瑚粉

            'secondary': '#4ECDC4',  # 薄荷绿

            'accent1': '#FFD166',    # 芒果黄

            'accent2': '#06D6A0',    # 青柠绿

            'accent3': '#118AB2',    # 天空蓝

            'background': '#F7F9FC', # 浅灰白

            'text': '#2D3142',       # 深灰蓝

            'light_text': '#6C757D'  # 浅灰色

        }

       

        # 设置背景颜色

        self.root.configure(bg=self.colors['background'])

       

        # 存储选择的文件

        self.selected_files = []

       

        # 创建界面

        self.create_widgets()

   

    def create_widgets(self):

        # 创建主框架

        main_frame = tk.Frame(self.root, bg=self.colors['background'])

        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

       

        # 创建左侧控制面板

        control_frame = tk.Frame(main_frame, bg=self.colors['background'], width=300)

        control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10)

       

        # 添加按钮

        self.create_buttons(control_frame)

       

        # 创建右侧文件列表和日志区域

        content_frame = tk.Frame(main_frame, bg=self.colors['background'])

        content_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10)

       

        # 文件列表区域

        files_frame = tk.LabelFrame(content_frame, text="待转换文件",

                                  font=("微软雅黑", 12),

                                  bg=self.colors['background'],

                                  fg=self.colors['text'])

        files_frame.pack(fill=tk.BOTH, expand=True, pady=10)

       

        # 文件列表

        self.create_file_list(files_frame)

       

        # 日志区域

        log_frame = tk.LabelFrame(content_frame, text="转换日志",

                                font=("微软雅黑", 12),

                                bg=self.colors['background'],

                                fg=self.colors['text'])

        log_frame.pack(fill=tk.BOTH, expand=True, pady=10)

       

        # 日志文本框

        self.create_log_text(log_frame)

   

    def create_buttons(self, parent):

        # 选择文件按钮

        select_btn = tk.Button(parent, text="选择PDF文件",

                             font=("微软雅黑", 14),

                             bg=self.colors['accent1'],

                             fg=self.colors['text'],

                             command=self.select_files,

                             relief=tk.RAISED,

                             bd=0,

                             height=2,

                             width=20)

        select_btn.pack(pady=15)

        select_btn.bind("<Enter>", lambda e: select_btn.config(bg="#FFE066"))

        select_btn.bind("<Leave>", lambda e: select_btn.config(bg=self.colors['accent1']))

       

        # 转换按钮

        convert_btn = tk.Button(parent, text="开始转换",

                              font=("微软雅黑", 14),

                              bg=self.colors['accent2'],

                              fg="white",

                              command=self.start_conversion,

                              relief=tk.RAISED,

                              bd=0,

                              height=2,

                              width=20)

        convert_btn.pack(pady=15)

        convert_btn.bind("<Enter>", lambda e: convert_btn.config(bg="#06E6A0"))

        convert_btn.bind("<Leave>", lambda e: convert_btn.config(bg=self.colors['accent2']))

       

        # 清空列表按钮

        clear_btn = tk.Button(parent, text="清空列表",

                            font=("微软雅黑", 14),

                            bg=self.colors['accent3'],

                            fg="white",

                            command=self.clear_files,

                            relief=tk.RAISED,

                            bd=0,

                            height=2,

                            width=20)

        clear_btn.pack(pady=15)

        clear_btn.bind("<Enter>", lambda e: clear_btn.config(bg="#119AB2"))

        clear_btn.bind("<Leave>", lambda e: clear_btn.config(bg=self.colors['accent3']))

   

    def create_file_list(self, parent):

        # 创建滚动条

        scrollbar = tk.Scrollbar(parent)

        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

       

        # 创建列表框

        self.file_listbox = tk.Listbox(parent,

                                     font=("微软雅黑", 10),

                                     bg="white",

                                     fg=self.colors['text'],

                                     selectbackground=self.colors['accent1'],

                                     selectforeground=self.colors['text'],

                                     width=70,

                                     height=10,

                                     yscrollcommand=scrollbar.set)

        self.file_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

       

        scrollbar.config(command=self.file_listbox.yview)

   

    def create_log_text(self, parent):

        # 创建滚动条

        scrollbar = tk.Scrollbar(parent)

        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

       

        # 创建文本框

        self.log_text = tk.Text(parent,

                              font=("微软雅黑", 10),

                              bg="white",

                              fg=self.colors['text'],

                              width=70,

                              height=8,

                              yscrollcommand=scrollbar.set,

                              state=tk.DISABLED)

        self.log_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

       

        scrollbar.config(command=self.log_text.yview)

   

    def select_files(self):

        files = filedialog.askopenfilenames(

            title="选择PDF文件",

            filetypes=[("PDF文件", "*.pdf"), ("所有文件", "*.*")]

        )

       

        if files:

            for file in files:

                if file not in self.selected_files:

                    self.selected_files.append(file)

                    self.file_listbox.insert(tk.END, os.path.basename(file))

            self.log("已添加 {} 个文件".format(len(files)))

   

    def clear_files(self):

        if self.selected_files:

            self.selected_files.clear()

            self.file_listbox.delete(0, tk.END)

            self.log("文件列表已清空")

        else:

            messagebox.showinfo("提示", "文件列表已为空")

   

    def start_conversion(self):

        if not self.selected_files:

            messagebox.showwarning("警告", "请先选择PDF文件")

            return

       

        # 选择输出目录

        output_dir = filedialog.askdirectory(title="选择输出目录")

        if not output_dir:

            return

       

        # 禁用转换按钮防止重复点击

        for widget in self.root.winfo_children():

            if isinstance(widget, tk.Frame) and widget.winfo_children():

                for child in widget.winfo_children():

                    if isinstance(child, tk.Frame) and child.winfo_children():

                        for btn in child.winfo_children():

                            if isinstance(btn, tk.Button) and btn["text"] == "开始转换":

                                btn.config(state=tk.DISABLED)

       

        # 在新线程中开始转换

        self.total_files = len(self.selected_files)

        self.current_file = 0

       

        thread = threading.Thread(target=self.convert_files, args=(output_dir,))

        thread.daemon = True

        thread.start()

   

    def convert_files(self, output_dir):

        self.log("开始转换文件...")

       

        # 确保输出目录存在

        if not os.path.exists(output_dir):

            try:

                os.makedirs(output_dir)

                self.log(f"已创建输出目录: {output_dir}")

            except Exception as e:

                self.log(f"创建输出目录失败: {str(e)}")

                # 在主线程中显示错误消息

                self.root.after(0, lambda: messagebox.showerror("错误", f"创建输出目录失败: {str(e)}"))

                # 重新启用转换按钮

                self.root.after(0, self._enable_convert_button)

                return

       

        success_count = 0

        fail_count = 0

       

        for i, pdf_path in enumerate(self.selected_files):

            self.current_file = i + 1

            filename = os.path.basename(pdf_path)

            docx_filename = os.path.splitext(filename)[0] + ".docx"

            docx_path = os.path.join(output_dir, docx_filename)

           

            try:

                self.log(f"转换中: {filename}")

               

                # 检查文件是否存在且可读

                if not os.path.exists(pdf_path):

                    raise FileNotFoundError(f"文件不存在: {pdf_path}")

               

                # 创建转换器并转换

                cv = Converter(pdf_path)

                cv.convert(docx_path, start=0, end=None)

                cv.close()

               

                self.log(f"转换完成: {docx_filename}")

                success_count += 1

            except Exception as e:

                error_msg = f"转换失败: {filename} - {str(e)}"

                self.log(error_msg)

                fail_count += 1

            finally:

                # 仅记录当前进度到日志

                self.log(f"进度: {self.current_file}/{self.total_files}")

       

        # 转换完成

        summary = f"转换完成!成功: {success_count}, 失败: {fail_count}"

        self.log(summary)

       

        # 重新启用转换按钮

        self.root.after(0, self._enable_convert_button)

       

        # 在主线程中显示完成消息

        self.root.after(0, lambda: messagebox.showinfo("完成", summary))

   

    def _enable_convert_button(self):

        """重新启用转换按钮的辅助方法"""

        for widget in self.root.winfo_children():

            if isinstance(widget, tk.Frame) and widget.winfo_children():

                for child in widget.winfo_children():

                    if isinstance(child, tk.Frame) and child.winfo_children():

                        for btn in child.winfo_children():

                            if isinstance(btn, tk.Button) and btn["text"] == "开始转换":

                                btn.config(state=tk.NORMAL)

                                break

   

    def log(self, message):

        timestamp = time.strftime("%H:%M:%S")

        log_message = f"[{timestamp}] {message}\n"

       

        self.log_text.config(state=tk.NORMAL)

        self.log_text.insert(tk.END, log_message)

        self.log_text.see(tk.END)  # 自动滚动到底部

        self.log_text.config(state=tk.DISABLED)

def check_dependencies():

    """检查程序所需的依赖项"""

    if not DEPENDENCY_AVAILABLE:

        root = tk.Tk()

        root.withdraw()  # 隐藏主窗口

        messagebox.showerror(

            "缺少依赖项",

            "未找到pdf2docx模块!\n\n请按照以下步骤安装依赖:\n1. 打开命令提示符\n2. 运行: pip install pdf2docx\n3. 然后重新启动程序"

        )

        root.destroy()

        return False

    return True

if __name__ == "__main__":

    # 调试输出

    print("程序启动中...")

   

    # 先检查依赖项

    if check_dependencies():

        try:

            print("依赖项检查通过,创建窗口...")

            root = tk.Tk()

            print("窗口创建成功,初始化应用...")

            app = PDFtoDOCXConverter(root)

            print("应用初始化完成,启动主循环...")

            root.mainloop()

        except Exception as e:

            print(f"程序运行出错: {str(e)}")

            import traceback

            traceback.print_exc()

            # 创建一个简单的错误提示窗口

            error_root = tk.Tk()

            error_root.title("错误")

            error_root.geometry("400x200")

           

            error_label = tk.Label(

                error_root,

                text=f"程序运行出错:\n{str(e)}",

                font=("微软雅黑", 10),

                justify=tk.LEFT,

                wraplength=380

            )

            error_label.pack(pady=20)

           

            ok_btn = tk.Button(

                error_root,

                text="确定",

                command=error_root.destroy,

                width=10

            )

            ok_btn.pack(pady=10)

           

            error_root.mainloop()

http://www.dtcms.com/a/566553.html

相关文章:

  • 怎么把网站关联到万网做网站网关备案
  • 网站的优化用什么软件wordpress门户型多栏设计
  • 长江商学院 网站建设妇幼能力建设网站
  • Java设计模式精讲---导学篇
  • 安阳网站如何做优化网站地址地图怎么做
  • 软件测试基础详解
  • 中介做网站的别打电话郑州有没有厉害的seo
  • 一做特卖的网站重庆江北营销型网站建设公司推荐
  • 【一文了解】八大排序-计数排序
  • X-Token 系列 HTTP 头部详解
  • 想用wordpress建立网站别样网站建设
  • 济南学网站建设哪里好建设通一年多少钱
  • 商城网站开发费用一般是多少东莞市微客巴巴做网站
  • 微秒延时us
  • 桐乡城市建设局网站邯郸小学网站建设
  • 沈阳网站公司排名龙华企业网站建设
  • CPU调度---协程
  • 网络安全活动总结
  • 站长之家alexa排名亚马逊一般在哪些网站上做推广
  • 直接用ip地址的网站怎么做宜宾县企业项目建设影响环境登记表网站
  • 计算机图形学·6 OpenGL编程3 谢尔宾斯基垫与三维编程
  • ThreadLocal 在项目中的应用
  • Vue动态路由的页面刷新的问题
  • 企业网站推广模式网站建设肆金手指排名9
  • 上海网站建设找缘魁915x1830建筑模板价格
  • 单页网站程序宠物交易网站模板
  • sparkCore读取数据的方式
  • 山东网站seo开发微信小程序开发api
  • Redis服务器配置
  • 优质ppt网站做网站接私活价格怎么算