-- coding: utf-8 --"""简历工具箱 v1.0 - PyQt5功能:简历生成/优化/打分/批量排序/导出作者:杨少平 | 公众号:Python学在坚持运行:python resume_tool.py依赖:pip install PyQt5 python-docx markdown"""import sys, os, re, json, uuidfrom datetime import datetimefrom PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,QLabel, QLineEdit, QTextEdit, QComboBox, QPushButton, QTabWidget,QGroupBox, QScrollArea, QSplitter, QFileDialog, QMessageBox,QTableWidget, QTableWidgetItem, QHeaderView, QProgressBar, QFrame,QFormLayout, QSpinBox, QCheckBox)from PyQt5.QtCore import Qtfrom PyQt5.QtGui import QFont, QColor==================== 简历评分引擎 ====================class ResumeScorer:"""简历评分:基于关键维度打分"""WEIGHTS = {"基本信息完整度": 15, "教育背景": 15, "工作经验": 25,"技能匹配度": 20, "项目经验": 15, "格式规范": 10,}KEYWORDS = {"技术": ["Python", "Java", "JavaScript", "Go", "C++", "SQL", "Docker", "K8s","React", "Vue", "Spring", "Django", "Flask", "TensorFlow", "PyTorch","AWS", "Azure", "Linux", "Git", "CI/CD", "微服务", "分布式"],"软技能": ["团队", "沟通", "领导", "管理", "协作", "解决问题", "创新"],}@staticmethoddef score(text): scores = {} total = 0 # 基本信息 info_keys = ["姓名", "电话", "邮箱", "手机", "email", "phone", "name"] info_count = sum(1 for k in info_keys if k.lower() in text.lower()) scores["基本信息完整度"] = min(15, int(info_count / 3 * 15)) # 教育背景 edu_keys = ["学历", "大学", "本科", "硕士", "博士", "学士", "education", "university"] edu_count = sum(1 for k in edu_keys if k.lower() in text.lower()) scores["教育背景"] = min(15, int(edu_count / 2 * 15)) # 工作经验 exp_keys = ["工作经验", "公司", "职位", "负责", "experience", "company", "负责人"] exp_count = sum(1 for k in exp_keys if k.lower() in text.lower()) year_match = re.findall(r'(\d+)\s*年', text) exp_years = max([int(y) for y in year_match] + [0]) scores["工作经验"] = min(25, int((exp_count / 3 * 15) + min(exp_years * 2, 10))) # 技能 tech_count = sum(1 for k in ResumeScorer.KEYWORDS["技术"] if k.lower() in text.lower()) scores["技能匹配度"] = min(20, int(tech_count / 5 * 20)) # 项目 proj_keys = ["项目", "project", "成果", "业绩", "贡献"] proj_count = sum(1 for k in proj_keys if k.lower() in text.lower()) scores["项目经验"] = min(15, int(proj_count / 2 * 15)) # 格式 lines = text.strip().split("\n") has_sections = sum(1 for l in lines if l.startswith("#") or l.startswith("##")) fmt_score = min(10, has_sections * 2 + (5 if len(text) > 500 else 0)) scores["格式规范"] = fmt_score total = sum(scores.values()) return total, scores@staticmethoddef suggest(text, scores): tips = [] if scores.get("基本信息完整度", 0) < 10: tips.append("建议补充完整的联系方式(姓名、电话、邮箱)") if scores.get("教育背景", 0) < 10: tips.append("建议详细描述教育背景(学校、专业、学历、时间)") if scores.get("工作经验", 0) < 15: tips.append("建议丰富工作经验描述,使用STAR法则(情境-任务-行动-结果)") if scores.get("技能匹配度", 0) < 12: tips.append("建议列出更多技术技能关键词,与目标岗位匹配") if scores.get("项目经验", 0) < 10: tips.append("建议增加项目经验,突出个人贡献和量化成果") if scores.get("格式规范", 0) < 6: tips.append("建议使用Markdown标题分节(# 基本信息、## 工作经验等)") if len(text) < 300: tips.append("简历内容偏少,建议扩充到500字以上") if not tips: tips.append("简历整体不错,可以进一步量化工作成果") return tips==================== 简历模板 ====================RESUME_TEMPLATE = """# 个人简历基本信息姓名:{name}电话:{phone}邮箱:{email}求职意向:{position}教育背景edu_school} {edu_major | edu_degree} {edu_time工作经验company1} {title1 | {work_time1}{work_desc1}专业技能{skills}项目经验{project1}项目描述:{proj_desc1}个人职责:{proj_role1}项目成果:{proj_result1}自我评价{self_eval}"""==================== Tab1: 简历生成与优化 ====================class ResumeEditorTab(QWidget):def init(self):super().init()self._build()def _build(self): splitter = QSplitter(Qt.Horizontal) lay = QVBoxLayout(self) lay.setContentsMargins(0, 0, 0, 0) lay.addWidget(splitter) # ---- 左侧:输入/生成 ---- left_scroll = QScrollArea() left_scroll.setWidgetResizable(True) left_scroll.setMinimumWidth(360) left_scroll.setMaximumWidth(450) left_w = QWidget() ll = QVBoxLayout(left_w) ll.setContentsMargins(12, 12, 12, 12) ll.setSpacing(8) # 导入 imp_row = QHBoxLayout() btn_import = QPushButton("📂 导入MD简历") btn_import.setStyleSheet("padding:8px;background:#1976d2;color:#fff;border:none;border-radius:4px;") btn_import.clicked.connect(self._import_md) imp_row.addWidget(btn_import) btn_sample = QPushButton("📝 加载示例") btn_sample.setStyleSheet("padding:8px;background:#ff9800;color:#fff;border:none;border-radius:4px;") btn_sample.clicked.connect(self._load_sample) imp_row.addWidget(btn_sample) ll.addLayout(imp_row) # 表单 g1 = QGroupBox("基本信息") g1l = QFormLayout() self.ed_name = QLineEdit(); self.ed_name.setPlaceholderText("张三") g1l.addRow("姓名:", self.ed_name) self.ed_phone = QLineEdit(); self.ed_phone.setPlaceholderText("13800138000") g1l.addRow("电话:", self.ed_phone) self.ed_email = QLineEdit(); self.ed_email.setPlaceholderText("zhangsan@email.com") g1l.addRow("邮箱:", self.ed_email) self.ed_position = QLineEdit(); self.ed_position.setPlaceholderText("Python开发工程师") g1l.addRow("求职意向:", self.ed_position) g1.setLayout(g1l) ll.addWidget(g1) g2 = QGroupBox("教育背景") g2l = QFormLayout() self.ed_school = QLineEdit(); self.ed_school.setPlaceholderText("XX大学") g2l.addRow("学校:", self.ed_school) self.ed_major = QLineEdit(); self.ed_major.setPlaceholderText("计算机科学") g2l.addRow("专业:", self.ed_major) self.cb_degree = QComboBox(); self.cb_degree.addItems(["本科", "硕士", "博士", "大专"]) g2l.addRow("学历:", self.cb_degree) self.ed_edu_time = QLineEdit(); self.ed_edu_time.setPlaceholderText("2018-2022") g2l.addRow("时间:", self.ed_edu_time) g2.setLayout(g2l) ll.addWidget(g2) g3 = QGroupBox("工作经验") g3l = QFormLayout() self.ed_company = QLineEdit(); self.ed_company.setPlaceholderText("XX科技有限公司") g3l.addRow("公司:", self.ed_company) self.ed_title = QLineEdit(); self.ed_title.setPlaceholderText("高级开发工程师") g3l.addRow("职位:", self.ed_title) self.ed_work_time = QLineEdit(); self.ed_work_time.setPlaceholderText("2022-至今") g3l.addRow("时间:", self.ed_work_time) self.ed_work_desc = QTextEdit(); self.ed_work_desc.setMaximumHeight(60) self.ed_work_desc.setPlaceholderText("负责核心业务系统开发...") g3l.addRow("描述:", self.ed_work_desc) g3.setLayout(g3l) ll.addWidget(g3) g4 = QGroupBox("技能与项目") g4l = QFormLayout() self.ed_skills = QTextEdit(); self.ed_skills.setMaximumHeight(50) self.ed_skills.setPlaceholderText("Python, Java, Docker, MySQL...") g4l.addRow("技能:", self.ed_skills) self.ed_proj = QLineEdit(); self.ed_proj.setPlaceholderText("智能数据分析平台") g4l.addRow("项目名:", self.ed_proj) self.ed_proj_desc = QTextEdit(); self.ed_proj_desc.setMaximumHeight(50) self.ed_proj_desc.setPlaceholderText("项目描述...") g4l.addRow("项目描述:", self.ed_proj_desc) self.ed_proj_role = QLineEdit(); self.ed_proj_role.setPlaceholderText("核心开发,负责后端架构设计") g4l.addRow("个人职责:", self.ed_proj_role) self.ed_proj_result = QLineEdit(); self.ed_proj_result.setPlaceholderText("系统性能提升50%") g4l.addRow("项目成果:", self.ed_proj_result) g4.setLayout(g4l) ll.addWidget(g4) self.ed_eval = QTextEdit(); self.ed_eval.setMaximumHeight(50) self.ed_eval.setPlaceholderText("热爱技术,善于学习...") ll.addWidget(QLabel("自我评价:")) ll.addWidget(self.ed_eval) btn_gen = QPushButton("🚀 生成简历") btn_gen.setStyleSheet("padding:10px;background:#d32f2f;color:#fff;border:none;border-radius:4px;font-size:14px;font-weight:bold;") btn_gen.clicked.connect(self._generate) ll.addWidget(btn_gen) ll.addStretch() left_scroll.setWidget(left_w) splitter.addWidget(left_scroll) # ---- 右侧:预览/评分/导出 ---- right = QWidget() rl = QVBoxLayout(right) rl.setContentsMargins(8, 8, 8, 8) rl.addWidget(QLabel("📄 简历预览(可直接编辑)")) self.editor = QTextEdit() self.editor.setFont(QFont("Microsoft YaHei", 11)) self.editor.setPlaceholderText("生成的简历将显示在这里...\n\n也可以直接导入MD文件编辑") self.editor.textChanged.connect(self._on_text_change) rl.addWidget(self.editor, 1) # 评分区 score_row = QHBoxLayout() self.lbl_score = QLabel("评分: --") self.lbl_score.setStyleSheet("font-size:18px;font-weight:bold;color:#1976d2;") score_row.addWidget(self.lbl_score) self.progress_score = QProgressBar() self.progress_score.setRange(0, 100) self.progress_score.setValue(0) self.progress_score.setMaximumHeight(12) score_row.addWidget(self.progress_score, 1) btn_score = QPushButton("📊 评分") btn_score.setStyleSheet("padding:6px 14px;background:#388e3c;color:#fff;border:none;border-radius:4px;") btn_score.clicked.connect(self._do_score) score_row.addWidget(btn_score) rl.addLayout(score_row) # 优化建议 self.tips_box = QTextEdit() self.tips_box.setMaximumHeight(100) self.tips_box.setReadOnly(True) self.tips_box.setStyleSheet("background:#fff8e1;border:1px solid #ffe082;border-radius:4px;font-size:12px;") self.tips_box.setPlaceholderText("点击「评分」查看优化建议...") rl.addWidget(self.tips_box) # 导出 exp_row = QHBoxLayout() btn_md = QPushButton("💾 导出MD") btn_md.setStyleSheet("padding:6px 14px;background:#1976d2;color:#fff;border:none;border-radius:4px;") btn_md.clicked.connect(lambda: self._export("md")) btn_doc = QPushButton("💾 导出Word") btn_doc.setStyleSheet("padding:6px 14px;background:#388e3c;color:#fff;border:none;border-radius:4px;") btn_doc.clicked.connect(lambda: self._export("docx")) self.lbl_count = QLabel("字数: 0") self.lbl_count.setStyleSheet("color:#888;") exp_row.addWidget(btn_md) exp_row.addWidget(btn_doc) exp_row.addStretch() exp_row.addWidget(self.lbl_count) rl.addLayout(exp_row) splitter.addWidget(right) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 1)def _generate(self): text = RESUME_TEMPLATE.format( name=self.ed_name.text() or "姓名", phone=self.ed_phone.text() or "电话", email=self.ed_email.text() or "邮箱", position=self.ed_position.text() or "求职意向", edu_school=self.ed_school.text() or "学校", edu_major=self.ed_major.text() or "专业", edu_degree=self.cb_degree.currentText(), edu_time=self.ed_edu_time.text() or "时间", company1=self.ed_company.text() or "公司", title1=self.ed_title.text() or "职位", work_time1=self.ed_work_time.text() or "时间", work_desc1=self.ed_work_desc.toPlainText() or "工作描述", skills=self.ed_skills.toPlainText() or "技能列表", project1=self.ed_proj.text() or "项目名称", proj_desc1=self.ed_proj_desc.toPlainText() or "项目描述", proj_role1=self.ed_proj_role.text() or "个人职责", proj_result1=self.ed_proj_result.text() or "项目成果", self_eval=self.ed_eval.toPlainText() or "自我评价", ) self.editor.setPlainText(text)def _import_md(self): path, _ = QFileDialog.getOpenFileName(self, "导入MD简历", "", "Markdown (*.md);;文本 (*.txt);;所有 (*)") if path: with open(path, "r", encoding="utf-8") as f: self.editor.setPlainText(f.read())def _load_sample(self): sample = RESUME_TEMPLATE.format( name="张三", phone="13800138000", email="zhangsan@email.com", position="Python高级开发工程师", edu_school="北京大学", edu_major="计算机科学与技术", edu_degree="硕士", edu_time="2016-2019", company1="XX科技有限公司", title1="高级Python开发工程师", work_time1="2019-至今", work_desc1="负责公司核心数据平台后端开发,使用Python/Django/Flask构建微服务架构,日处理数据量1000万+", skills="Python, Java, Docker, Kubernetes, MySQL, Redis, Elasticsearch, Git, Linux, CI/CD", project1="智能数据分析平台", proj_desc1="基于Python+Elasticsearch+Vue的企业级数据分析平台,支持多维度数据查询和可视化", proj_role1="核心开发,负责后端架构设计、ES检索优化、API开发", proj_result1="系统查询性能提升60%,支撑日均100万次查询", self_eval="5年Python开发经验,熟悉分布式系统架构,具备良好的团队协作和沟通能力", ) self.editor.setPlainText(sample)def _on_text_change(self): self.lbl_count.setText(f"字数: {len(self.editor.toPlainText())}")def _do_score(self): text = self.editor.toPlainText() if not text.strip(): QMessageBox.warning(self, "提示", "请先输入或生成简历内容"); return total, scores = ResumeScorer.score(text) self.lbl_score.setText(f"评分: {total}/100") self.progress_score.setValue(total) if total >= 80: color = "#388e3c" elif total >= 60: color = "#ff9800" else: color = "#d32f2f" self.lbl_score.setStyleSheet(f"font-size:18px;font-weight:bold;color:{color};") # 详细分数 detail = "\n".join(f" {k}: {v}/{ResumeScorer.WEIGHTS[k]}" for k, v in scores.items()) tips = ResumeScorer.suggest(text, scores) self.tips_box.setPlainText(f"📊 各维度得分:\n{detail}\n\n💡 优化建议:\n" + "\n".join(f" • {t}" for t in tips))def _export(self, fmt): text = self.editor.toPlainText() if not text.strip(): QMessageBox.warning(self, "提示", "没有内容可导出"); return if fmt == "md": path, _ = QFileDialog.getSaveFileName(self, "导出MD", "resume.md", "Markdown (*.md)") if path: with open(path, "w", encoding="utf-8") as f: f.write(text) QMessageBox.information(self, "成功", f"已导出到 {path}") elif fmt == "docx": try: from docx import Document path, _ = QFileDialog.getSaveFileName(self, "导出Word", "resume.docx", "Word (*.docx)") if path: doc = Document() for line in text.split("\n"): line = line.strip() if line.startswith("# "): doc.add_heading(line[2:], level=1) elif line.startswith("## "): doc.add_heading(line[3:], level=2) elif line.startswith("### "): doc.add_heading(line[4:], level=3) elif line.startswith("- "): doc.add_paragraph(line[2:], style="List Bullet") elif line: doc.add_paragraph(line) doc.save(path) QMessageBox.information(self, "成功", f"已导出到 {path}") except ImportError: QMessageBox.warning(self, "缺少依赖", "pip install python-docx")==================== Tab2: 批量简历分析 ====================class BatchAnalysisTab(QWidget):def init(self):super().init()self.resumes = [] # [{"name":, "text":, "score":, "scores":}]self._build()def _build(self): lay = QVBoxLayout(self) lay.setContentsMargins(12, 12, 12, 12) # 顶部操作 top = QHBoxLayout() btn_upload = QPushButton("📂 批量上传MD简历") btn_upload.setStyleSheet("padding:8px 16px;background:#1976d2;color:#fff;border:none;border-radius:4px;font-size:13px;") btn_upload.clicked.connect(self._upload) top.addWidget(btn_upload) btn_clear = QPushButton("🗑 清空") btn_clear.setStyleSheet("padding:8px 16px;background:#757575;color:#fff;border:none;border-radius:4px;") btn_clear.clicked.connect(self._clear) top.addWidget(btn_clear) btn_export = QPushButton("📥 导出分析报告") btn_export.setStyleSheet("padding:8px 16px;background:#388e3c;color:#fff;border:none;border-radius:4px;") btn_export.clicked.connect(self._export_report) top.addWidget(btn_export) top.addStretch() self.lbl_stats = QLabel("已加载: 0 份简历") self.lbl_stats.setStyleSheet("color:#888;font-size:13px;") top.addWidget(self.lbl_stats) lay.addLayout(top) # 统计卡片 cards = QHBoxLayout() self.card_total = self._card("📄 总数", "0", "#1976d2") self.card_avg = self._card("📊 平均分", "0", "#ff9800") self.card_max = self._card("🏆 最高分", "0", "#388e3c") self.card_min = self._card("📉 最低分", "0", "#d32f2f") cards.addWidget(self.card_total) cards.addWidget(self.card_avg) cards.addWidget(self.card_max) cards.addWidget(self.card_min) lay.addLayout(cards) # 排名表格 self.table = QTableWidget() self.table.setColumnCount(9) self.table.setHorizontalHeaderLabels(["排名", "文件名", "总分", "基本信息", "教育背景", "工作经验", "技能匹配", "项目经验", "格式规范"]) self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.setAlternatingRowColors(True) self.table.setStyleSheet("QTableWidget{font-size:12px;} QTableWidget::item:selected{background:#e3f2fd;}") self.table.cellClicked.connect(self._on_row_click) lay.addWidget(self.table, 1) # 底部预览 self.preview = QTextEdit() self.preview.setMaximumHeight(180) self.preview.setReadOnly(True) self.preview.setFont(QFont("Microsoft YaHei", 10)) self.preview.setPlaceholderText("点击表格行查看简历内容和优化建议...") lay.addWidget(self.preview)def _card(self, title, value, color): w = QFrame() w.setStyleSheet(f"background:#fff;border:1px solid #e0e0e0;border-radius:8px;border-left:4px solid {color};") l = QVBoxLayout(w) l.setContentsMargins(12, 8, 12, 8) lbl_t = QLabel(title); lbl_t.setStyleSheet("color:#888;font-size:11px;") lbl_v = QLabel(value); lbl_v.setStyleSheet(f"color:{color};font-size:22px;font-weight:bold;") lbl_v.setObjectName("card_value") l.addWidget(lbl_t); l.addWidget(lbl_v) return wdef _update_card(self, card, value): card.findChild(QLabel, "card_value").setText(str(value))def _upload(self): paths, _ = QFileDialog.getOpenFileNames(self, "选择MD简历文件", "", "Markdown (*.md);;文本 (*.txt);;所有 (*)") if not paths: return for p in paths: try: with open(p, "r", encoding="utf-8") as f: text = f.read() total, scores = ResumeScorer.score(text) self.resumes.append({"name": os.path.basename(p), "text": text, "score": total, "scores": scores}) except Exception as e: print(f"读取失败: {p}{e}") self._refresh()def _clear(self): self.resumes.clear() self._refresh() self.preview.clear()def _refresh(self): # 按分数降序排序 self.resumes.sort(key=lambda x: x["score"], reverse=True) self.table.setRowCount(len(self.resumes)) for i, r in enumerate(self.resumes): self.table.setItem(i, 0, QTableWidgetItem(str(i + 1))) self.table.setItem(i, 1, QTableWidgetItem(r["name"])) score_item = QTableWidgetItem(str(r["score"])) if r["score"] >= 80: score_item.setForeground(QColor("#388e3c")) elif r["score"] >= 60: score_item.setForeground(QColor("#ff9800")) else: score_item.setForeground(QColor("#d32f2f")) score_item.setFont(QFont("", -1, QFont.Bold)) self.table.setItem(i, 2, score_item) keys = ["基本信息完整度", "教育背景", "工作经验", "技能匹配度", "项目经验", "格式规范"] for j, k in enumerate(keys): self.table.setItem(i, 3 + j, QTableWidgetItem(str(r["scores"].get(k, 0)))) # 统计 n = len(self.resumes) self.lbl_stats.setText(f"已加载: {n} 份简历") self._update_card(self.card_total, n) if n > 0: scores = [r["score"] for r in self.resumes] self._update_card(self.card_avg, f"{sum(scores)/n:.1f}") self._update_card(self.card_max, max(scores)) self._update_card(self.card_min, min(scores)) else: for c in [self.card_avg, self.card_max, self.card_min]: self._update_card(c, "0")def _on_row_click(self, row, col): if 0 <= row < len(self.resumes): r = self.resumes[row] tips = ResumeScorer.suggest(r["text"], r["scores"]) self.preview.setPlainText( f"📄 {r['name']} | 评分: {r['score']}/100\n\n" f"💡 优化建议:\n" + "\n".join(f" • {t}" for t in tips) + f"\n\n{'='*40}\n简历内容:\n{'='*40}\n{r['text'][:500]}..." )def _export_report(self): if not self.resumes: QMessageBox.warning(self, "提示", "请先上传简历"); return path, _ = QFileDialog.getSaveFileName(self, "导出分析报告", "resume_report.md", "Markdown (*.md)") if not path: return n = len(self.resumes) scores = [r["score"] for r in self.resumes] md = f"# 简历批量分析报告\n\n" md += f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}\n\n" md += f"## 统计概览\n\n" md += f"| 指标 | 数值 |\n|------|------|\n" md += f"| 简历总数 | {n} |\n" md += f"| 平均分 | {sum(scores)/n:.1f} |\n" md += f"| 最高分 | {max(scores)} |\n" md += f"| 最低分 | {min(scores)} |\n\n" md += f"## 排名详情\n\n" md += "| 排名 | 文件名 | 总分 | 基本信息 | 教育 | 工作 | 技能 | 项目 | 格式 |\n" md += "|------|--------|------|----------|------|------|------|------|------|\n" for i, r in enumerate(self.resumes): s = r["scores"] md += f"| {i+1} | {r['name']} | {r['score']} | {s.get('基本信息完整度',0)} | {s.get('教育背景',0)} | {s.get('工作经验',0)} | {s.get('技能匹配度',0)} | {s.get('项目经验',0)} | {s.get('格式规范',0)} |\n" md += f"\n## 各简历优化建议\n\n" for i, r in enumerate(self.resumes): tips = ResumeScorer.suggest(r["text"], r["scores"]) md += f"### {i+1}. {r['name']} ({r['score']}分)\n\n" for t in tips: md += f"- {t}\n" md += "\n" with open(path, "w", encoding="utf-8") as f: f.write(md) QMessageBox.information(self, "成功", f"报告已导出到:\n{path}")==================== 主窗口 ====================class ResumeToolApp(QMainWindow):def init(self):super().init()self.setWindowTitle("📄 简历工具箱 v1.0 | Python学在坚持")self.setMinimumSize(1000, 650)self.resize(1200, 750)tabs = QTabWidget()tabs.setStyleSheet("""QTabBar::tab{padding:10px 24px;font-size:13px;}QTabBar::tab:selected{background:#1976d2;color:#fff;border-radius:4px 4px 0 0;}""")tabs.addTab(ResumeEditorTab(), "📝 简历生成与优化")tabs.addTab(BatchAnalysisTab(), "📊 批量分析与排名")self.setCentralWidget(tabs)self.statusBar().showMessage("公众号: Python学在坚持 | 微信: ysp2338084 | 作者: 杨少平")if name == "main":app = QApplication(sys.argv)app.setStyle("Fusion")app.setFont(QFont("Microsoft YaHei", 10))win = ResumeToolApp()win.show()sys.exit(app.exec_())