放假了,目前只能先这样了,祝大家新年快乐!
注意:
运行前确保电脑安装好
[color=]python环境
PyQt6
pyinstaller>=6.0.0
python-version>=3.8,
成品 https://wwzd.lanzn.com/iXKRH2ljlera
[Python] 纯文本查看 复制代码import sys
import os
from PyQt6.QtWidgets import (QApplication, QMainWindow, QPushButton,
QFileDialog, QLabel, QVBoxLayout, QWidget,
QProgressBar, QCheckBox, QGroupBox, QGridLayout,
QMessageBox, QLineEdit)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QIcon, QFont
import subprocess
class ConvertThread(QThread):
progress = pyqtSignal(str)
finished = pyqtSignal(bool, str)
def __init__(self, file_path, options):
super().__init__()
self.file_path = file_path
self.options = options
def run(self):
try:
# 基础命令
command = ['pyinstaller', '--clean'] # 添加 --clean 确保清理之前的构建
# 添加用户选择的选项
if self.options['onefile']:
command.append('--onefile') # 生成单文件
else:
command.append('--onedir') # 生成文件夹
if self.options['noconsole']:
command.append('--noconsole') # 无控制台
command.append('--windowed') # 添加 windowed 选项确保是 GUI 程序
if self.options['icon'] and os.path.exists(self.options['icon']):
command.extend(['--icon', self.options['icon']])
if self.options['name']:
command.extend(['--name', self.options['name']])
# 添加目标文件
command.append(self.file_path)
self.progress.emit(f"执行命令: {' '.join(command)}")
# 运行转换命令
result = subprocess.run(
command,
capture_output=True,
text=True,
check=False
)
# 检查转换结果
if result.returncode == 0:
self.finished.emit(True, "转换成功!请查看dist文件夹")
else:
error_msg = result.stderr or "未知错误"
self.progress.emit(f"错误输出: {error_msg}") # 显示详细错误信息
self.finished.emit(False, f"转换失败: {error_msg}")
except Exception as e:
self.finished.emit(False, f"发生错误: {str(e)}")
class Py2ExeConverter(QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle("Python转EXE工具 v2.0")
self.setFixedSize(600, 400)
# 创建主窗口部件
main_widget = QWidget()
self.setCentralWidget(main_widget)
# 创建主布局
layout = QVBoxLayout()
# 文件选择区域
file_group = QGroupBox("文件选择")
file_layout = QGridLayout()
self.file_label = QLabel("未选择文件")
self.file_label.setStyleSheet("padding: 5px; background-color: #f0f0f0; border-radius: 3px;")
select_button = QPushButton("选择Python文件")
select_button.setStyleSheet("background-color: #4CAF50; color: white; padding: 5px;")
file_layout.addWidget(self.file_label, 0, 0)
file_layout.addWidget(select_button, 0, 1)
file_group.setLayout(file_layout)
# 选项区域
options_group = QGroupBox("转换选项")
options_layout = QGridLayout()
self.onefile_check = QCheckBox("生成单个文件")
self.onefile_check.setChecked(True)
self.noconsole_check = QCheckBox("隐藏控制台窗口")
self.noconsole_check.setChecked(True)
# 图标选择
self.icon_label = QLabel("图标文件:")
self.icon_path = QLineEdit()
self.icon_path.setPlaceholderText("可选:选择.ico图标文件")
icon_button = QPushButton("浏览")
icon_button.clicked.connect(self.select_icon)
# 输出文件名
self.name_label = QLabel("输出文件名:")
self.name_input = QLineEdit()
self.name_input.setPlaceholderText("可选:指定输出的exe文件名")
options_layout.addWidget(self.onefile_check, 0, 0)
options_layout.addWidget(self.noconsole_check, 0, 1)
options_layout.addWidget(self.icon_label, 1, 0)
options_layout.addWidget(self.icon_path, 1, 1)
options_layout.addWidget(icon_button, 1, 2)
options_layout.addWidget(self.name_label, 2, 0)
options_layout.addWidget(self.name_input, 2, 1)
options_group.setLayout(options_layout)
# 进度显示
self.progress_label = QLabel("准备就绪")
self.progress_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.progress_bar = QProgressBar()
self.progress_bar.setTextVisible(False)
# 转换按钮
convert_button = QPushButton("开始转换")
convert_button.setStyleSheet("""
QPushButton {
background-color: #2196F3;
color: white;
padding: 8px;
font-weight: bold;
border-radius: 4px;
}
QPushButton:hover {
background-color: #1976D2;
}
""")
# 添加所有部件到主布局
layout.addWidget(file_group)
layout.addWidget(options_group)
layout.addWidget(self.progress_label)
layout.addWidget(self.progress_bar)
layout.addWidget(convert_button)
# 设置主布局
main_widget.setLayout(layout)
# 连接信号
select_button.clicked.connect(self.select_file)
convert_button.clicked.connect(self.convert_to_exe)
self.selected_file = None
self.convert_thread = None
def select_file(self):
file_name, _ = QFileDialog.getOpenFileName(
self,
"选择Python文件",
"",
"Python Files (*.py)"
)
if file_name:
self.selected_file = file_name
self.file_label.setText(f"已选择: {os.path.basename(file_name)}")
# 自动设置输出文件名
default_name = os.path.splitext(os.path.basename(file_name))[0]
self.name_input.setText(default_name)
def select_icon(self):
icon_path, _ = QFileDialog.getOpenFileName(
self,
"选择图标文件",
"",
"Icon Files (*.ico)"
)
if icon_path:
self.icon_path.setText(icon_path)
def update_progress(self, message):
self.progress_label.setText(message)
self.progress_bar.setMaximum(0) # 显示忙碌状态
def conversion_complete(self, success, message):
# 重新启用转换按钮
for child in self.findChildren(QPushButton):
if child.text() == "开始转换":
child.setEnabled(True)
self.progress_bar.setMaximum(100)
self.progress_bar.setValue(100 if success else 0)
self.progress_label.setText(message)
if success:
QMessageBox.information(self, "转换完成", message)
else:
QMessageBox.warning(self, "转换失败", message)
def convert_to_exe(self):
if not self.selected_file:
QMessageBox.warning(self, "警告", "请先选择Python文件!")
return
# 禁用转换按钮,防止重复点击
self.sender().setEnabled(False)
self.progress_label.setText("正在转换中...")
self.progress_bar.setMaximum(0)
options = {
'onefile': self.onefile_check.isChecked(),
'noconsole': self.noconsole_check.isChecked(),
'icon': self.icon_path.text(),
'name': self.name_input.text().strip()
}
self.convert_thread = ConvertThread(self.selected_file, options)
self.convert_thread.progress.connect(self.update_progress)
self.convert_thread.finished.connect(self.conversion_complete)
self.convert_thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
# 设置应用程序样式
app.setStyle('Fusion')
window = Py2ExeConverter()
window.show()
sys.exit(app.exec())