利用tkinter函数构造MD5加密的可视化操作界面

GitHub文档地址:
https://github.com/gao7025/auto_entry_md5.git

引言

利用tkinter构造一个图形界面的创建函数,主要实现了文件选择、MD5加密处理、结果预览和下载等功能。下面是主要涉及的功能模块:主框架、文件选择部分、MD5加密部分、结果预览部分、下载功能和状态栏等功能。

  1. 支持CSV、Excel和文本文件的上传
  2. 可以同时选择多个列进行MD5加密
  3. 加密过程在后台线程中进行,不会阻塞界面
  4. 显示加密结果的预览信息
  5. 将加密结果导出为Excel文件

1. 创建界面组件
    def create_widgets(self):
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 文件选择部分
        file_frame = ttk.LabelFrame(main_frame, text="文件选择", padding="10")
        file_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(file_frame, text="选择文件:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        
        self.file_path_var = tk.StringVar()
        ttk.Entry(file_frame, textvariable=self.file_path_var, width=50).grid(row=0, column=1, padx=5, pady=5)
        
        ttk.Button(file_frame, text="浏览...", command=self.browse_file).grid(row=0, column=2, padx=5, pady=5)
        ttk.Button(file_frame, text="上传文件", command=self.load_file).grid(row=0, column=3, padx=5, pady=5)
        
        # 进度条
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(file_frame, variable=self.progress_var, maximum=100, length=300)
        self.progress_bar.grid(row=1, column=0, columnspan=4, padx=5, pady=5, sticky=tk.W+tk.E)
        
        # MD5加密部分
        md5_frame = ttk.LabelFrame(main_frame, text="MD5加密处理", padding="10")
        md5_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(md5_frame, text="选择要加密的列:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        
        # 创建一个带滚动条的列表框用于多选列
        listbox_frame = ttk.Frame(md5_frame)
        listbox_frame.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
        
        self.columns_listbox = tk.Listbox(listbox_frame, selectmode=tk.MULTIPLE, width=30, height=5)
        self.columns_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = ttk.Scrollbar(listbox_frame, orient=tk.VERTICAL, command=self.columns_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.columns_listbox.config(yscrollcommand=scrollbar.set)
        
        self.encrypt_btn = ttk.Button(md5_frame, text="加密所选列", command=self.encrypt_columns, state=tk.DISABLED)
        self.encrypt_btn.grid(row=0, column=2, padx=5, pady=5)
        
        # 结果预览部分
        results_frame = ttk.LabelFrame(main_frame, text="结果预览", padding="10")
        results_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        # 创建一个带滚动条的文本区域
        text_frame = ttk.Frame(results_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)
        
        self.result_text = tk.Text(text_frame, wrap=tk.WORD, height=10)
        self.result_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = ttk.Scrollbar(text_frame, command=self.result_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.result_text.config(yscrollcommand=scrollbar.set)
        
        # 下载按钮
        self.download_btn = ttk.Button(main_frame, text="下载加密结果", command=self.download_results, state=tk.DISABLED)
        self.download_btn.pack(pady=10)
        
        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("就绪")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
2. 打开文件浏览器选择文件,加载并显示文件内容
    def browse_file(self):
        file_path = filedialog.askopenfilename(
            filetypes=[
                ("CSV文件", "*.csv"), 
                ("Excel文件", "*.xlsx;*.xls"), 
                ("文本文件", "*.txt"),
                ("所有文件", "*.*")
            ]
        )
        if file_path:
            self.file_path_var.set(file_path)
            self.file_path = file_path
    
    def load_file(self):
        if not self.file_path:
            messagebox.showerror("错误", "请先选择一个文件")
            return
        
        # 清空结果文本区域和列表框
        self.result_text.delete(1.0, tk.END)
        self.columns_listbox.delete(0, tk.END)
        self.encrypted_data = None
        
        # 更新状态栏和启用进度条
        self.status_var.set("正在加载文件...")
        self.progress_var.set(0)
        self.progress_bar.start()
        
        # 在单独的线程中执行加载,避免界面卡顿
        load_thread = threading.Thread(target=self._perform_load)
        load_thread.daemon = True
        load_thread.start()
    def _perform_load(self):
        try:
            # 读取文件
            file_ext = os.path.splitext(self.file_path)[1].lower()
            
            if file_ext == '.csv':
                self.data = pd.read_csv(self.file_path)
            elif file_ext in ['.xlsx', '.xls']:
                self.data = pd.read_excel(self.file_path)
            elif file_ext == '.txt':
                # 尝试检测分隔符
                with open(self.file_path, 'r') as f:
                    first_line = f.readline()
                    if '\t' in first_line:
                        self.data = pd.read_csv(self.file_path, sep='\t')
                    elif ',' in first_line:
                        self.data = pd.read_csv(self.file_path, sep=',')
                    else:
                        self.data = pd.read_csv(self.file_path, sep=None, engine='python')
            else:
                # 尝试用 pandas 读取其他格式
                try:
                    self.data = pd.read_csv(self.file_path)
                except Exception as e:
                    self.update_ui(lambda: messagebox.showerror("错误", f"不支持的文件格式: {e}"))
                    self.update_ui(lambda: self.status_var.set("就绪"))
                    self.update_ui(lambda: self.progress_bar.stop())
                    return
            
            # 更新进度
            self.update_ui(lambda: self.progress_var.set(50))
            self.update_ui(lambda: self.status_var.set("正在准备预览..."))
            
            # 更新列选择列表框
            self.update_ui(self.update_columns_listbox)
            
            # 显示数据预览
            self.update_ui(self.display_data_preview)
            
            # 启用加密按钮
            self.update_ui(lambda: self.encrypt_btn.config(state=tk.NORMAL))
            
            # 完成
            self.update_ui(lambda: self.progress_var.set(100))
            self.update_ui(lambda: self.progress_bar.stop())
            self.update_ui(lambda: self.status_var.set("文件加载完成"))
            
        except Exception as e:
            # 显示错误信息并记录日志
            error_msg = f"加载文件时出错: {str(e)}"
            self.update_ui(lambda: messagebox.showerror("错误", error_msg))
            self.update_ui(lambda: self.progress_bar.stop())
            self.update_ui(lambda: self.status_var.set("加载失败"))
            log_error(type(e), e, e.__traceback__)
3.对选中的列进行MD5加密
    def encrypt_columns(self):
        if self.data is None or self.data.empty:
            messagebox.showerror("错误", "没有数据可加密")
            return
        
        # 获取所有选中的列
        selected_indices = self.columns_listbox.curselection()
        if not selected_indices:
            messagebox.showerror("错误", "请选择至少一个列进行加密")
            return
        
        # 提取选中的列名(去除类型标记)
        selected_columns = []
        for i in selected_indices:
            col_text = self.columns_listbox.get(i)
            # 如果列名包含类型标记,则提取原始列名
            if '(' in col_text and ')' in col_text:
                col_name = col_text.split('(')[0].strip()
            else:
                col_name = col_text
            selected_columns.append(col_name)
        
        # 检查选中的列是否存在于数据中
        invalid_cols = [col for col in selected_columns if col not in self.data.columns]
        if invalid_cols:
            messagebox.showerror("错误", f"选中的列不存在: {', '.join(invalid_cols)}")
            return
        
        # 更新状态栏
        self.status_var.set("正在加密数据...")
        self.progress_var.set(0)
        self.progress_bar.start()
        
        # 在单独的线程中执行加密,避免界面卡顿
        encryption_thread = threading.Thread(target=self._perform_encryption, args=(selected_columns,))
        encryption_thread.daemon = True
        encryption_thread.start()
    
    def _perform_encryption(self, selected_columns):
        try:
            # 创建数据副本
            self.encrypted_data = self.data.copy()
            
            # 对每列进行加密
            total_cols = len(selected_columns)
            for i, col in enumerate(selected_columns):
                # 更新进度
                progress = (i / total_cols) * 100
                self.update_ui(lambda p=progress: self.progress_var.set(p))
                
                # 创建新列名
                new_col = f"{col}_md5"
                
                # 对每一行进行MD5加密
                # 先将列转换为字符串类型
                self.encrypted_data[new_col] = self.data[col].astype(str).apply(lambda x: self._md5_encrypt(x) if pd.notna(x) else x)
            
            # 显示加密结果预览
            self.update_ui(self.display_encrypted_preview)
            
            # 启用下载按钮
            self.update_ui(lambda: self.download_btn.config(state=tk.NORMAL))
            
            # 完成
            self.update_ui(lambda: self.progress_var.set(100))
            self.update_ui(lambda: self.progress_bar.stop())
            self.update_ui(lambda: self.status_var.set("加密完成"))
            
            messagebox.showinfo("成功", f"已对选中的 {total_cols} 列进行MD5加密")
            
        except Exception as e:
            error_msg = f"加密过程中出错: {str(e)}"
            self.update_ui(lambda: messagebox.showerror("错误", error_msg))
            self.update_ui(lambda: self.progress_bar.stop())
            self.update_ui(lambda: self.status_var.set("加密失败"))
            log_error(type(e), e, e.__traceback__)
    
    def _md5_encrypt(self, text):
        return hashlib.md5(text.encode('utf-8')).hexdigest()
4.通过pyinstaller函数对文件进行exe打包
pyinstaller -w --onedir --hidden-import pandas --hidden-import openpyxl md5_encryption_tool.py

参数说明:

-w 或 --windowed:不显示命令行窗口(适合 GUI 应用)
-F 或 --onefile:打包成单个可执行的exe文件
–onedir 打包成包含所有依赖的文件夹(而不是单个exe文件)
–hidden-import:指定需要包含的隐藏依赖

在这里插入图片描述

结果展示

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值