一、完整代碼實現
import sys
import os
import json
import pyzipper
from datetime import datetime
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,QPushButton, QLineEdit, QLabel, QFileDialog,QMessageBox, QProgressBar)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QFont, QIconclass ZipThread(QThread):progress = pyqtSignal(int)finished = pyqtSignal(str)error = pyqtSignal(str)def __init__(self, source, password, parent=None):super().__init__(parent)self.source = sourceself.password = passwordself.zip_path = f"{os.path.splitext(source)}_encrypted.zip"def run(self):try:total_files = self.calculate_total_files()processed = 0with pyzipper.AESZipFile(self.zip_path, 'w', compression=pyzipper.ZIP_LZMA,encryption=pyzipper.WZ_AES) as zf:zf.setpassword(self.password.encode())if os.path.isdir(self.source):for root, dirs, files in os.walk(self.source):for file in files:full_path = os.path.join(root, file)arcname = os.path.relpath(full_path, start=self.source)zf.write(full_path, arcname)processed += 1self.progress.emit(int((processed/total_files)*100))else:zf.write(self.source, os.path.basename(self.source))self.progress.emit(100)self.save_metadata()self.finished.emit(self.zip_path)except Exception as e:self.error.emit(str(e))def calculate_total_files(self):if os.path.isfile(self.source):return 1count = 0for root, dirs, files in os.walk(self.source):count += len(files)return countdef save_metadata(self):metadata = {"timestamp": datetime.now().isoformat(),"source_path": self.source,"zip_path": self.zip_path,"file_size": os.path.getsize(self.zip_path),"algorithm": "AES-256"}with open(self.zip_path + ".json", 'w') as f:json.dump(metadata, f, indent=2)class SecureZipApp(QWidget):def __init__(self):super().__init__()self.selected_path = ""self.initUI()self.applyStyles()def initUI(self):self.setWindowTitle('安全文件壓縮器')self.setWindowIcon(QIcon('lock_icon.png'))self.setFixedSize(500, 400)# 界面組件self.title_label = QLabel("安全加密壓縮工具")self.path_label = QLabel("已選路徑:無")self.progress_bar = QProgressBar()self.status_label = QLabel("就緒")self.pwd_input = QLineEdit()self.pwd_input.setPlaceholderText("輸入加密密碼(至少8位)")self.pwd_input.setEchoMode(QLineEdit.Password)# 按鈕組btn_layout = QHBoxLayout()self.file_btn = QPushButton("📁 選擇文件")self.dir_btn = QPushButton("📂 選擇文件夾")self.start_btn = QPushButton("🔒 開始加密壓縮")# 布局設置main_layout = QVBoxLayout()main_layout.addWidget(self.title_label, alignment=Qt.AlignCenter)main_layout.addSpacing(20)main_layout.addWidget(self.path_label)main_layout.addWidget(self.pwd_input)main_layout.addSpacing(15)btn_layout.addWidget(self.file_btn)btn_layout.addWidget(self.dir_btn)main_layout.addLayout(btn_layout)main_layout.addSpacing(30)main_layout.addWidget(self.progress_bar)main_layout.addWidget(self.status_label)main_layout.addWidget(self.start_btn)self.setLayout(main_layout)# 信號連接self.file_btn.clicked.connect(self.select_file)self.dir_btn.clicked.connect(self.select_dir)self.start_btn.clicked.connect(self.start_compression)def applyStyles(self):self.setStyleSheet("""\QWidget {\background-color: #F5F7FA;\font-family: 'Segoe UI';\}\QLabel#title_label {\font-size: 24px;\color: #2C3E50;\font-weight: bold;\}\QPushButton {\background-color: #4CAF50;\color: white;\border: none;\padding: 10px 20px;\border-radius: 5px;\font-size: 14px;\}\QPushButton:hover {\background-color: #45a049;\}\QLineEdit {\padding: 8px;\border: 2px solid #BDC3C7;\border-radius: 4px;\font-size: 14px;\}\QProgressBar {\height: 20px;\text-align: center;\border: 2px solid #BDC3C7;\border-radius: 5px;\}\QProgressBar::chunk {\background-color: #4CAF50;\width: 10px;\}\""")self.title_label.setObjectName("title_label")self.title_label.setFont(QFont("Arial", 16, QFont.Bold))self.status_label.setStyleSheet("color: #7F8C8D; font-size: 12px;")def select_file(self):path, _ = QFileDialog.getOpenFileName(self, "選擇文件")if path:self.selected_path = pathself.path_label.setText(f"已選文件:{os.path.basename(path)}")self.status_label.setText("就緒")def select_dir(self):path = QFileDialog.getExistingDirectory(self, "選擇文件夾")if path:self.selected_path = pathself.path_label.setText(f"已選文件夾:{os.path.basename(path)}")self.status_label.setText("就緒")def start_compression(self):if not self.selected_path:QMessageBox.warning(self, "警告", "請先選擇文件或文件夾")returnif len(self.pwd_input.text()) < 8:QMessageBox.warning(self, "警告", "密碼長度至少8位")returnself.thread = ZipThread(self.selected_path, self.pwd_input.text())self.thread.progress.connect(self.update_progress)self.thread.finished.connect(self.on_success)self.thread.error.connect(self.on_error)self.thread.start()self.start_btn.setEnabled(False)self.status_label.setText("正在壓縮...")def update_progress(self, value):self.progress_bar.setValue(value)def on_success(self, zip_path):self.start_btn.setEnabled(True)self.status_label.setText("操作完成")QMessageBox.information(self, "成功", f"加密壓縮完成!\n保存路徑:{zip_path}\n元數據文件:{zip_path}.json")def on_error(self, message):self.start_btn.setEnabled(True)self.status_label.setText("操作失敗")QMessageBox.critical(self, "錯誤", f"發生錯誤:{message}")if __name__ == '__main__':app = QApplication(sys.argv)window = SecureZipApp()window.show()sys.exit(app.exec_())
二、界面美化特色
-
現代UI設計
- 采用扁平化設計風格
- 使用系統圖標符號(📁📂🔒)提升直觀性
- 自定義QSS樣式表實現漸變按鈕和圓角邊框
-
交互優化
- 實時路徑顯示
- 動態進度條反饋
- 狀態標簽提示當前操作階段
- 按鈕禁用狀態防止重復操作
-
安全增強
- 密碼強度驗證(至少8位)
- 密碼輸入掩碼顯示
- 元數據文件獨立存儲(避免密碼泄露)
-
響應式布局
- 固定窗口尺寸防止變形
- 智能間距控制
- 組件對齊優化
三、使用說明
- 選擇文件/文件夾
- 輸入8位以上加密密碼
- 點擊加密壓縮按鈕
- 查看生成的
.zip
文件和同名的.json
元數據文件
由小藝AI生成<xiaoyi.huawei.com>