# -*- coding: utf-8 -*-
# @Create Time : 2024/4/22 13:38
# @Edit Time : 2024/4/23 10:59
# @Author : Tim
# @File : UI.py
# @Software : PyCharm
import re
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pandas as pd
import threading
# 新增曲目列表
SONG_NAMES = ["歌曲A", "歌曲B", "歌曲C"]
# 存储每首歌曲对应的评分
SONG_SCORES = {}
def center_window(window, width, height):
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
x = (screen_width // 2) - (width // 2)
y = (screen_height // 2) - (height // 2)
window.geometry(f"{width}x{height}+{x}+{y}")
def is_valid_integer(text):
return re.match(r'^\d+$', text) and 1 <= int(text) <= 120
def save_to_excel_thread(name, age, gender, score1, score2, score3):
data = {
"姓名": [name],
"年龄": [age],
"性别": [gender],
"歌曲A": [score1],
"歌曲B": [score2],
"歌曲C": [score3]
}
try:
df = pd.DataFrame(data)
# 这里假设默认当前工作目录是可写的,更健壮的实现应考虑指定路径或检查权限
df.to_excel('data.xlsx', index=False)
messagebox.showinfo("成功", "数据已保存到Excel文件")
except Exception as e:
messagebox.showerror("错误", f"保存失败: {e}")
def save_to_excel(name_entry, age_entry, gender_combobox, score_combobox1, score_combobox2, score_combobox3):
name = name_entry.get().strip()
age = age_entry.get().strip()
gender = gender_combobox.get().strip()
score1 = score_combobox1.get().strip().split(".")[0]
score2 = score_combobox2.get().strip().split(".")[0]
score3 = score_combobox3.get().strip().split(".")[0]
if not all([name, age, gender, score1, score2, score3]):
messagebox.showerror("错误", "请确保所有字段都已填写")
return
# 输入验证
if not is_valid_integer(age):
messagebox.showerror("错误", "年龄:请输入1-120的整数")
return
# 使用线程来异步保存数据
save_thread = threading.Thread(target=save_to_excel_thread,
args=(name, age, gender, score1, score2, score3))
save_thread.start()
def assessors_info_window(root):
# 评价人信息窗口
assessors_frame = ttk.Frame(root, padding=(10, 10))
assessors_frame.pack(fill=tk.X, padx=10, pady=10)
# 评价人信息
assessors_label = tk.Label(assessors_frame, text="评价人员信息", font=("Arial", 10, "bold"))
assessors_label.grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
# 姓名部分
name_label = tk.Label(assessors_frame, text="姓名:")
name_label.grid(row=1, column=0, sticky=tk.E, padx=(0, 10))
name_entry = tk.Entry(assessors_frame, width=20)
name_entry.grid(row=1, column=1, padx=(10, 0), pady=(0, 10))
# 年龄部分
age_label = tk.Label(assessors_frame, text="年龄:")
age_label.grid(row=2, column=0, sticky=tk.E, padx=(0, 10))
age_entry = tk.Entry(assessors_frame, width=20)
age_entry.grid(row=2, column=1, padx=(10, 0), pady=(0, 10))
# 性别部分
gender_label = tk.Label(assessors_frame, text="性别:")
gender_label.grid(row=3, column=0, sticky=tk.E, padx=(0, 10))
gender_combobox = ttk.Combobox(assessors_frame, values=["男", "女"], state="readonly", width=18)
gender_combobox.grid(row=3, column=1, padx=(10, 0), pady=(0, 10))
return name_entry, age_entry, gender_combobox
def song_and_score_window(root):
global SONG_NAMES
song_assessment_score_list = ['1.极差', '2.很差', '3.略差', '4.一般', '5.略好',
'6.良好', '7.很好', '8.非常好', '9.极好', '10.完美']
# 评价曲目与评分窗口
song_and_score_frame = ttk.Frame(root, padding=(10, 10))
song_and_score_frame.pack(fill=tk.X, padx=10, pady=10)
# 评价内容
content_label = tk.Label(song_and_score_frame, text="评价内容", font=("Arial", 10, "bold"))
content_label.grid(row=0, column=0, sticky=tk.W, padx=(0, 10))
# 评分 1.极差 2.很差 3.略差 4.一般 5.略好]\n[6.良好 7.很好 8.非常好 9.极好 10.完美
score_label1 = tk.Label(song_and_score_frame, text=f"{SONG_NAMES[0]}:")
score_label1.grid(row=1, column=0, sticky=tk.E, padx=(47, 10))
score_combobox1 = ttk.Combobox(song_and_score_frame, values=[item for item in song_assessment_score_list],
state="readonly",
width=18)
score_combobox1.grid(row=1, column=1, padx=(10, 0), pady=(0, 10))
score_label2 = tk.Label(song_and_score_frame, text=f"{SONG_NAMES[1]}:")
score_label2.grid(row=2, column=0, sticky=tk.E, padx=(47, 10))
score_combobox2 = ttk.Combobox(song_and_score_frame, values=[item for item in song_assessment_score_list],
state="readonly",
width=18)
score_combobox2.grid(row=2, column=1, padx=(10, 0), pady=(0, 10))
score_label3 = tk.Label(song_and_score_frame, text=f"{SONG_NAMES[2]}:")
score_label3.grid(row=3, column=0, sticky=tk.E, padx=(47, 10))
score_combobox3 = ttk.Combobox(song_and_score_frame, values=[item for item in song_assessment_score_list],
state="readonly",
width=18)
score_combobox3.grid(row=3, column=1, padx=(10, 0), pady=(0, 10))
return score_combobox1, score_combobox2, score_combobox3
def create_gui():
root = tk.Tk()
root.title("主观评价")
name_entry, age_entry, gender_combobox = assessors_info_window(root)
score_combobox1, score_combobox2, score_combobox3 = song_and_score_window(root)
# 添加保存按钮
save_button = ttk.Button(root, text="保存到EXCEL",
command=lambda: save_to_excel(name_entry, age_entry, gender_combobox, score_combobox1,
score_combobox2, score_combobox3))
save_button.pack(side=tk.BOTTOM, pady=10)
width, height = 350, 380
center_window(root, width, height)
root.geometry(f"{width}x{height}")
root.mainloop()
if __name__ == "__main__":
create_gui()
pyinstaller -F -w UI.py
使用pyinstaller打包生成的EXE在执行过程中报错,如下图所示。
我在pycharm中可以正常运行UI.py,然而打包之后却报缺少这个方法,说明这个方法有可能与我的代码执行无关,尝试忽略该方法,重新打包,执行以下指令。
pyinstaller --onefile --hidden-import=openpyxl.cell._writer UI.py
可以正常运行。问题解决。