浔川代码编辑器 v4.0 上线公告
为持续打磨产品体验全面响应浔川代码编辑器 v3.1.0 版本的高频用户建议浔川社团研发团队以 “精简冗余、优化流程”为核心完成了 v4.0 版本的研发与测试。本次迭代聚焦编码核心场景通过简化操作流程、精简冗余功能为广大开发者带来更轻快、更高效的编码体验。浔川代码编辑器 v4.0 原定于2026 年 3 月 7 日 正式上线实际于3月8日上线。现将相关更新内容、上线信息及升级指引公告如下一、核心更新源于用户反馈聚焦体验升级本次版本更新所有优化方向均基于 v3.1.0 版本用户使用数据与反馈建议直击使用痛点让编码操作更贴合开发者实际需求。1. 登录流程极致简化针对用户集中反馈的 “登录步骤繁琐、验证环节冗余” 问题v4.0 版本对登录架构进行全面重构在保障账号安全的前提下实现登录效率大幅提升新增手机号一键登录功能支持免密快速登录无需手机验证码取消无实际安全增益的冗余验证环节与验证码流程经实测用户平均登录耗时较旧版本缩短 60%保留核心账号安全校验机制做到便捷性与安全性兼顾。2. 冗余进制功能移除结合海量用户实际使用场景数据分析研发团队决定移除使用率不足 0.5% 的十二进制与十六进制转换功能聚焦核心编码需求简化编辑器功能面板布局减少非核心功能对操作的干扰核心编码工具入口更突出降低功能查找成本减少后台资源占用提升编辑器整体运行流畅度尤其优化低配置设备的使用体验。二、上线信息与升级指引正式上线时间2026 年 3 月 8 日适用平台本次 v4.0 版本同步上线多端客户端网页版因需完成浏览器兼容性测试与服务器压力适配暂不随本次上线具体上线时间请关注浔川社团官方后续公告。Windowsx64/Arm64macOSIntel/SiliconLinuxdeb/rpm升级方式本次更新支持自动更新与手动下载两种方式升级后将自动保留用户原有配置、项目数据与使用习惯无需重新设置自动更新当前使用 v3.1.0 及以上版本的用户可在程序中找到版本弹窗更新提示点击「立即更新」即可一键完成升级手动下载登录CSDN账号搜索浔川社团官方博客http://xunchuanshetuan.blog.csdn.net在文章找到本篇文章即可。三、风险提示与反馈渠道重要提醒为保障数据安全建议各位开发者在升级 v4.0 版本前对本地重要项目文件进行备份避免极端情况下出现数据丢失问题。问题反馈渠道若在版本升级或使用过程中遇到任何问题可通过以下官方渠道反馈研发团队将及时响应处理官方客服渠道http://xunchuanshetuan.blog.csdn.net官网反馈入口浔川社团官方博客首页「意见建议」专属板块import tkinter as tk from tkinter import ttk, scrolledtext, messagebox, filedialog, simpledialog import sqlite3 import hashlib import os import sys import requests import json from datetime import datetime # -------------------------- 全局配置与常量 -------------------------- # 软件信息 SOFT_NAME 浔川代码编辑器 SOFT_VERSION 4.0.0 # 远程更新地址(示例,可替换为自己的服务器地址) UPDATE_API https://jsonplaceholder.typicode.com/posts/1 # 测试接口 # 数据库文件 DB_FILE editor_user.db # 编辑器默认配置 DEFAULT_FONT (Consolas, 12) HIGHLIGHT_COLORS { keyword: #0000FF, # 关键字-蓝色 string: #A31515, # 字符串-红色 comment: #008000, # 注释-绿色 number: #FF00FF # 数字-紫色 } # Python关键字(语法高亮用) PYTHON_KEYWORDS { False, None, True, and, as, assert, async, await, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield } # 已登录用户全局变量 LOGGED_USER None # 统一协议版本号 PROTOCOL_VERSION 4.0 # -------------------------- 数据库初始化(用户/配置/协议) -------------------------- def init_database(): 初始化SQLite数据库,创建用户表、配置表、协议表 conn sqlite3.connect(DB_FILE) c conn.cursor() # 1. 用户表:id(主键)、用户名、密码(MD5)、注册时间、是否同意协议 c.execute(CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, reg_time TEXT NOT NULL, agree_protocol INTEGER DEFAULT 0)) # 2. 编辑器配置表:用户关联、字体、字号、窗口大小 c.execute(CREATE TABLE IF NOT EXISTS editor_config (user_id INTEGER PRIMARY KEY, font TEXT NOT NULL, font_size INTEGER NOT NULL, win_size TEXT DEFAULT 800x600, FOREIGN KEY(user_id) REFERENCES users(id))) # 3. 用户协议表:版本、内容、更新时间(单条数据) c.execute(CREATE TABLE IF NOT EXISTS user_protocol (version TEXT PRIMARY KEY, content TEXT NOT NULL, update_time TEXT NOT NULL)) # 初始化默认用户协议(若不存在) c.execute(SELECT * FROM user_protocol WHERE version?, (PROTOCOL_VERSION,)) if not c.fetchone(): default_protocol [浔川代码编辑器用户协议] 版本:4.0 更新时间:2026-01-29 1. 本软件为免费开源工具,仅供个人学习和非商业使用; 2. 用户需妥善保管自己的账号密码,因密码泄露造成的损失由用户自行承担; 3. 软件支持在线资源更新,更新过程中请保证网络通畅; 4. 禁止使用本软件编写、运行违法违规、危害网络安全的代码; 5. 本协议的最终解释权归软件开发者所有,如有更新将在启动时提示. c.execute(INSERT INTO user_protocol VALUES (?, ?, ?), (PROTOCOL_VERSION, default_protocol.strip(), datetime.now().strftime(%Y-%m-%d %H:%M:%S))) conn.commit() conn.close() # -------------------------- 工具函数(加密/数据库操作) -------------------------- def md5_encrypt(s): MD5加密,用于密码存储 m hashlib.md5() m.update(s.encode(utf-8)) return m.hexdigest() def db_query(sql, params()): 数据库查询操作 conn sqlite3.connect(DB_FILE) c conn.cursor() c.execute(sql, params) result c.fetchall() conn.close() return result def db_execute(sql, params()): 数据库增删改操作 conn sqlite3.connect(DB_FILE) c conn.cursor() try: c.execute(sql, params) conn.commit() return True except sqlite3.IntegrityError: return False # 唯一键冲突(如用户名重复) finally: conn.close() # -------------------------- 资源更新模块 -------------------------- def check_update(): 检测远程更新,返回更新信息(版本/更新内容/下载地址) try: response requests.get(UPDATE_API, timeout5) if response.status_code 200: # 模拟更新数据(实际项目替换为真实返回格式) update_data { latest_version: 1.1.0, current_version: SOFT_VERSION, update_content: 1. 新增Python语法高亮优化;2. 修复保存文件乱码问题;3. 新增字体大小一键调整;4. 优化登录状态持久化, download_url: https://github.com/xxx/python-editor/archive/refs/tags/v1.1.0.zip } return update_data else: return None except Exception as e: return None def update_resource(): 执行资源更新:检测更新→确认→提示下载 messagebox.showinfo(检查更新, 正在检测最新版本,请稍候...) update_info check_update() if not update_info: messagebox.showinfo(检查更新, 当前已是最新版本,或网络异常无法检测更新!) return # 版本比较(简单数字比较,实际可使用semver库) def version2num(v): return list(map(int, v.split(.))) if version2num(update_info[latest_version]) version2num(SOFT_VERSION): messagebox.showinfo(检查更新, f当前已是最新版本(v{SOFT_VERSION}),无需更新!) return # 展示更新内容并确认 confirm messagebox.askyesno( 发现新版本, f检测到新版本:v{update_info[latest_version]}\n f当前版本:v{SOFT_VERSION}\n\n f更新内容:\n{update_info[update_content]}\n\n 是否前往下载更新包?(下载后请解压替换原文件并重启) ) if confirm: import webbrowser webbrowser.open(update_info[download_url]) # -------------------------- 用户协议模块 -------------------------- def show_protocol_window(parent, must_agreeFalse): 展示用户协议窗口,must_agreeTrue时必须同意才能继续 protocol_win tk.Toplevel(parent) protocol_win.title(用户协议) protocol_win.geometry(600x500) protocol_win.resizable(False, False) protocol_win.transient(parent) protocol_win.grab_set() # 模态窗口,禁止操作父窗口 # 获取协议内容(使用统一的协议版本号) protocol_data db_query(SELECT content, version FROM user_protocol WHERE version?, (PROTOCOL_VERSION,)) if protocol_data: protocol_content protocol_data[0][0] protocol_version protocol_data[0][1] else: protocol_content 暂无协议内容 protocol_version 未知版本 # 协议标题 ttk.Label(protocol_win, textf用户协议(版本:{protocol_version}), font(SimHei, 14, bold)).pack(pady10) # 协议内容(滚动文本) - 先创建可编辑的文本框,插入内容后设为只读 protocol_text scrolledtext.ScrolledText(protocol_win, font(SimSun, 10), wraptk.WORD, statetk.NORMAL) protocol_text.insert(tk.END, protocol_content) protocol_text.config(statetk.DISABLED) # 插入内容后设为只读 protocol_text.pack(filltk.BOTH, expandTrue, padx20, pady5) # 按钮框架 btn_frame ttk.Frame(protocol_win) btn_frame.pack(pady10) def agree_action(): 同意协议 if must_agree and LOGGED_USER: # 更新用户协议同意状态 user_id db_query(SELECT id FROM users WHERE username?, (LOGGED_USER,))[0][0] db_execute(UPDATE users SET agree_protocol1 WHERE id?, (user_id,)) protocol_win.destroy() def cancel_action(): 取消/拒绝协议 protocol_win.destroy() if must_agree: # 必须同意才能使用,直接退出登录 global LOGGED_USER LOGGED_USER None parent.quit() messagebox.showwarning(提示, 您必须同意用户协议才能使用本软件!) # 同意/取消按钮 ttk.Button(btn_frame, text同意, commandagree_action, width10).grid(row0, column0, padx20) if must_agree: ttk.Button(btn_frame, text拒绝, commandcancel_action, width10).grid(row0, column1) else: ttk.Button(btn_frame, text关闭, commandcancel_action, width10).grid(row0, column1) # 窗口居中(修复居中逻辑) protocol_win.update_idletasks() # 先更新窗口尺寸 parent_x parent.winfo_x() parent_y parent.winfo_y() parent_w parent.winfo_width() parent_h parent.winfo_height() win_w protocol_win.winfo_width() win_h protocol_win.winfo_height() x parent_x (parent_w - win_w) // 2 y parent_y (parent_h - win_h) // 2 protocol_win.geometry(f{x}{y}) # -------------------------- 注册登录模块 -------------------------- class LoginRegisterWindow: 登录/注册窗口 def __init__(self, root): self.root root self.root.title(f{SOFT_NAME} - 登录/注册) self.root.geometry(400x350) self.root.resizable(False, False) self.current_frame None # 当前显示的框架(登录/注册) self.create_widgets() self.show_login_frame() # 默认显示登录框 def create_widgets(self): 创建基础容器 self.main_frame ttk.Frame(self.root, padding20) self.main_frame.pack(filltk.BOTH, expandTrue) # 标题 ttk.Label(self.main_frame, textSOFT_NAME, font(SimHei, 18, bold)).pack(pady10) ttk.Label(self.main_frame, textf版本:v{SOFT_VERSION}, font(SimHei, 10)).pack(pady5) def clear_frame(self): 清空当前框架 if self.current_frame: self.current_frame.destroy() self.current_frame ttk.Frame(self.main_frame) self.current_frame.pack(filltk.BOTH, expandTrue, pady20) def show_login_frame(self): 显示登录框架 self.clear_frame() # 用户名 ttk.Label(self.current_frame, text用户名:).grid(row0, column0, stickytk.W, pady10) self.login_user ttk.Entry(self.current_frame, width25) self.login_user.grid(row0, column1, pady10) # 密码 ttk.Label(self.current_frame, text密 码:).grid(row1, column0, stickytk.W, pady10) self.login_pwd ttk.Entry(self.current_frame, width25, show*) self.login_pwd.grid(row1, column1, pady10) # 登录按钮 ttk.Button(self.current_frame, text登录, commandself.login, width15).grid(row2, column0, columnspan2, pady15) # 切换注册 ttk.Label(self.current_frame, text还没有账号?).grid(row3, column0, stickytk.E) ttk.Button(self.current_frame, text立即注册, commandself.show_register_frame, styleLink.TButton).grid(row3, column1, stickytk.W) # 自定义链接样式(无边框) self.root.style ttk.Style() self.root.style.configure(Link.TButton, borderwidth0, foreground#0000FF) def show_register_frame(self): 显示注册框架 self.clear_frame() # 用户名 ttk.Label(self.current_frame, text用户名:).grid(row0, column0, stickytk.W, pady8) self.reg_user ttk.Entry(self.current_frame, width25) self.reg_user.grid(row0, column1, pady8) # 密码 ttk.Label(self.current_frame, text密 码:).grid(row1, column0, stickytk.W, pady8) self.reg_pwd ttk.Entry(self.current_frame, width25, show*) self.reg_pwd.grid(row1, column1, pady8) # 确认密码 ttk.Label(self.current_frame, text确认密码:).grid(row2, column0, stickytk.W, pady8) self.reg_pwd2 ttk.Entry(self.current_frame, width25, show*) self.reg_pwd2.grid(row2, column1, pady8) # 注册按钮 ttk.Button(self.current_frame, text注册, commandself.register, width15).grid(row3, column0, columnspan2, pady15) # 切换登录 ttk.Label(self.current_frame, text已有账号?).grid(row4, column0, stickytk.E) ttk.Button(self.current_frame, text立即登录, commandself.show_login_frame, styleLink.TButton).grid(row4, column1, stickytk.W) def login(self): 登录逻辑 username self.login_user.get().strip() password self.login_pwd.get().strip() if not username or not password: messagebox.showwarning(提示, 用户名和密码不能为空!) return # 验证用户 pwd_md5 md5_encrypt(password) user_data db_query(SELECT id, agree_protocol FROM users WHERE username? AND password?, (username, pwd_md5)) if not user_data: messagebox.showerror(错误, 用户名或密码错误!) return # 全局登录用户 global LOGGED_USER LOGGED_USER username user_id, agree_protocol user_data[0] # 初始化用户编辑器配置(若不存在) if not db_query(SELECT * FROM editor_config WHERE user_id?, (user_id,)): db_execute(INSERT INTO editor_config (user_id, font, font_size) VALUES (?, ?, ?), (user_id, DEFAULT_FONT[0], DEFAULT_FONT[1])) # 未同意协议则强制展示 if agree_protocol 0: show_protocol_window(self.root, must_agreeTrue) # 关闭登录窗口,打开主编辑器 self.root.destroy() main_editor tk.Tk() CodeEditor(main_editor) main_editor.mainloop() def register(self): 注册逻辑 username self.reg_user.get().strip() password self.reg_pwd.get().strip() password2 self.reg_pwd2.get().strip() # 验证输入 if not username or not password: messagebox.showwarning(提示, 用户名和密码不能为空!) return if len(username) 3 or len(password) 6: messagebox.showwarning(提示, 用户名至少3位,密码至少6位!) return if password ! password2: messagebox.showwarning(提示, 两次输入的密码不一致!) return # 插入数据库 pwd_md5 md5_encrypt(password) reg_time datetime.now().strftime(%Y-%m-%d %H:%M:%S) success db_execute( INSERT INTO users (username, password, reg_time) VALUES (?, ?, ?), (username, pwd_md5, reg_time) ) if success: messagebox.showinfo(成功, 注册成功!请登录使用~) self.show_login_frame() else: messagebox.showerror(错误, 用户名已存在!) # -------------------------- 代码编辑器核心模块(语法高亮/行号) -------------------------- class CodeEditor: 代码编辑器主窗口(核心功能) def __init__(self, root): self.root root self.root.title(f{SOFT_NAME} - 未命名文件 - 登录用户:{LOGGED_USER}) self.root.geometry(800x600) self.file_path None # 当前打开的文件路径 self.user_id db_query(SELECT id FROM users WHERE username?, (LOGGED_USER,))[0][0] self.load_user_config() # 加载用户配置 # 创建UI self.create_menu() self.create_editor() self.bind_shortcuts() # 绑定快捷键 self.root.protocol(WM_DELETE_WINDOW, self.on_closing) # 关闭窗口事件 def load_user_config(self): 加载用户编辑器配置 config db_query(SELECT font, font_size, win_size FROM editor_config WHERE user_id?, (self.user_id,))[0] self.font (config[0], config[1]) self.win_size config[2] self.root.geometry(self.win_size) def save_user_config(self): 保存用户编辑器配置 win_size f{self.root.winfo_width()}x{self.root.winfo_height()} db_execute( UPDATE editor_config SET font?, font_size?, win_size? WHERE user_id?, (self.font[0], self.font[1], win_size, self.user_id) ) def create_menu(self): 创建菜单栏(文件/编辑/视图/帮助) menubar tk.Menu(self.root) self.root.config(menumenubar) # 1. 文件菜单 file_menu tk.Menu(menubar, tearoff0) file_menu.add_command(label新建, commandself.new_file, acceleratorCtrlN) file_menu.add_command(label打开, commandself.open_file, acceleratorCtrlO) file_menu.add_command(label保存, commandself.save_file, acceleratorCtrlS) file_menu.add_command(label另存为, commandself.save_as_file, acceleratorCtrlShiftS) file_menu.add_separator() file_menu.add_command(label退出, commandself.on_closing) menubar.add_cascade(label文件, menufile_menu) # 2. 编辑菜单 edit_menu tk.Menu(menubar, tearoff0) edit_menu.add_command(label撤销, commandlambda: self.text_editor.edit_undo(), acceleratorCtrlZ) edit_menu.add_command(label重做, commandlambda: self.text_editor.edit_redo(), acceleratorCtrlY) edit_menu.add_separator() edit_menu.add_command(label全选, commandlambda: self.text_editor.tag_add(tk.SEL, 1.0, tk.END), acceleratorCtrlA) edit_menu.add_command(label复制, commandlambda: self.text_editor.event_generate(Copy), acceleratorCtrlC) edit_menu.add_command(label剪切, commandlambda: self.text_editor.event_generate(Cut), acceleratorCtrlX) edit_menu.add_command(label粘贴, commandlambda: self.text_editor.event_generate(Paste), acceleratorCtrlV) menubar.add_cascade(label编辑, menuedit_menu) # 3. 视图菜单 view_menu tk.Menu(menubar, tearoff0) view_menu.add_command(label增大字体, commandself.increase_font, acceleratorCtrl) view_menu.add_command(label减小字体, commandself.decrease_font, acceleratorCtrl-) menubar.add_cascade(label视图, menuview_menu) # 4. 帮助菜单 help_menu tk.Menu(menubar, tearoff0) help_menu.add_command(label检查更新, commandupdate_resource) help_menu.add_command(label用户协议, commandlambda: show_protocol_window(self.root, must_agreeFalse)) help_menu.add_command(label关于软件, commandself.show_about) menubar.add_cascade(label帮助, menuhelp_menu) def create_editor(self): 创建代码编辑区域(行号编辑框语法高亮) # 主框架 editor_frame ttk.Frame(self.root) editor_frame.pack(filltk.BOTH, expandTrue) # 行号框(只读) self.line_num tk.Text(editor_frame, width4, fontself.font, statetk.NORMAL, bg#F0F0F0, wraptk.NONE) self.line_num.pack(sidetk.LEFT, filltk.Y) self.line_num.config(statetk.DISABLED) # 代码编辑框(可滚动) self.text_editor scrolledtext.ScrolledText(editor_frame, fontself.font, wraptk.NONE, undoTrue, maxundo-1) # 开启撤销/重做 self.text_editor.pack(sidetk.LEFT, filltk.BOTH, expandTrue) self.text_editor.focus_set() # 配置语法高亮标签 for tag, color in HIGHLIGHT_COLORS.items(): self.text_editor.tag_configure(tag, foregroundcolor) # 绑定事件:内容变化时更新行号和语法高亮 self.text_editor.bind(KeyRelease, self.update_editor) self.text_editor.bind(MouseRelease, self.update_editor) self.text_editor.bind(Configure, self.update_editor) # 初始更新行号 self.update_line_num() def bind_shortcuts(self): 绑定快捷键 self.root.bind(Control-n, lambda e: self.new_file()) self.root.bind(Control-o, lambda e: self.open_file()) self.root.bind(Control-s, lambda e: self.save_file()) self.root.bind(Control-Shift-S, lambda e: self.save_as_file()) self.root.bind(Control-plus, lambda e: self.increase_font()) self.root.bind(Control-minus, lambda e: self.decrease_font()) def update_line_num(self): 更新行号 # 获取总行数 line_count int(self.text_editor.index(tk.END).split(.)[0]) - 1 # 更新行号框 self.line_num.config(statetk.NORMAL) self.line_num.delete(1.0, tk.END) self.line_num.insert(tk.END, \n.join(map(str, range(1, line_count 1)))) self.line_num.config(statetk.DISABLED) def syntax_highlight(self): Python语法高亮(关键字/字符串/注释/数字) # 清除原有标签 for tag in HIGHLIGHT_COLORS.keys(): self.text_editor.tag_remove(tag, 1.0, tk.END) content self.text_editor.get(1.0, tk.END) lines content.split(\n) for line_idx, line in enumerate(lines): line_num line_idx 1 pos 0 while pos len(line): # 匹配单行注释(#) if line[pos] #: self.text_editor.tag_add(comment, f{line_num}.{pos}, f{line_num}.end) break # 匹配字符串(单引号/双引号) elif line[pos] in (, ): quote line[pos] end_pos line.find(quote, pos 1) if end_pos ! -1: self.text_editor.tag_add(string, f{line_num}.{pos}, f{line_num}.{end_pos1}) pos end_pos 1 else: pos 1 # 匹配数字(0-9/./-) elif line[pos].isdigit() or (line[pos] - and pos1 len(line) and line[pos1].isdigit()): end_pos pos while end_pos len(line) and (line[end_pos].isdigit() or line[end_pos] .): end_pos 1 self.text_editor.tag_add(number, f{line_num}.{pos}, f{line_num}.{end_pos}) pos end_pos # 匹配关键字 elif line[pos].isalpha() or line[pos] _: end_pos pos while end_pos len(line) and (line[end_pos].isalnum() or line[end_pos] _): end_pos 1 word line[pos:end_pos] if word in PYTHON_KEYWORDS: self.text_editor.tag_add(keyword, f{line_num}.{pos}, f{line_num}.{end_pos}) pos end_pos else: pos 1 def update_editor(self, eventNone): 更新编辑器(行号语法高亮) self.update_line_num() self.syntax_highlight() # -------------------------- 编辑器基础功能 -------------------------- def new_file(self): 新建文件 if self.check_unsaved(): self.text_editor.delete(1.0, tk.END) self.file_path None self.root.title(f{SOFT_NAME} - 未命名文件 - 登录用户:{LOGGED_USER}) def open_file(self): 打开文件 if self.check_unsaved(): file_path filedialog.askopenfilename( title打开文件, filetypes[(Python文件, *.py), (文本文件, *.txt), (所有文件, *.*)] ) if file_path: self.file_path file_path with open(file_path, r, encodingutf-8) as f: content f.read() self.text_editor.delete(1.0, tk.END) self.text_editor.insert(1.0, content) self.root.title(f{SOFT_NAME} - {os.path.basename(file_path)} - 登录用户:{LOGGED_USER}) def save_file(self): 保存文件 if not self.file_path: self.save_as_file() else: content self.text_editor.get(1.0, tk.END) with open(self.file_path, w, encodingutf-8) as f: f.write(content) messagebox.showinfo(成功, 文件保存成功!) def save_as_file(self): 另存为文件 file_path filedialog.asksaveasfilename( title另存为, defaultextension.py, filetypes[(Python文件, *.py), (文本文件, *.txt), (所有文件, *.*)] ) if file_path: self.file_path file_path self.save_file() self.root.title(f{SOFT_NAME} - {os.path.basename(file_path)} - 登录用户:{LOGGED_USER}) def increase_font(self): 增大字体 new_size self.font[1] 2 self.font (self.font[0], new_size) self.text_editor.config(fontself.font) self.line_num.config(fontself.font) self.save_user_config() def decrease_font(self): 减小字体(最小10号) if self.font[1] 10: new_size self.font[1] - 2 self.font (self.font[0], new_size) self.text_editor.config(fontself.font) self.line_num.config(fontself.font) self.save_user_config() def check_unsaved(self): 检查是否有未保存内容,返回True表示可继续操作,False表示取消 content self.text_editor.get(1.0, tk.END).strip() if content and not self.file_path: confirm messagebox.askyesno(提示, 当前有未保存的内容,是否放弃?) return confirm return True def show_about(self): 显示关于软件 about_info f {SOFT_NAME} 版本:v{SOFT_VERSION} 开发语言:Python Tkinter 数据库:SQLite3 功能:代码编辑/注册登录/资源更新/用户协议 本软件为免费开源工具,仅供学习使用! 更新时间:2026-01-29 messagebox.showinfo(关于软件, about_info.strip()) def on_closing(self): 关闭窗口前的确认 if self.check_unsaved(): self.save_user_config() # 保存用户配置 self.root.destroy() sys.exit() # -------------------------- 程序入口 -------------------------- if __name__ __main__: # 初始化数据库 init_database() # 启动登录/注册窗口 login_root tk.Tk() LoginRegisterWindow(login_root) login_root.mainloop()

相关新闻

npm突然没了

npm突然没了

我有NVM 所以重新安装了 重新安装当前版本: 先卸载目前的 22.21.0: bash nvm uninstall 22.21.0 再重新装回来: bash nvm install 22.21.0 nvm use 22.21.0

2026/5/17 10:22:17 阅读更多 →
一篇吃透 Java 泛型:语法与底层原理

一篇吃透 Java 泛型:语法与底层原理

泛型一、泛型的概念二、泛型的语法1. 泛型类 / 接口2. 泛型方法三、泛型类的使用四、泛型如何编译的(面试常考)1. 擦除机制五、泛型的上界一、泛型的概念 泛型就是参数化类型,把数据类型当作参数传递,把类型当作参数传进去,用什么类型&#…

2026/7/3 2:51:46 阅读更多 →
2026年GEO优化服务商哪家好?权威排名TOP5,亚森SEO稳居榜首!

2026年GEO优化服务商哪家好?权威排名TOP5,亚森SEO稳居榜首!

2026年GEO优化服务商哪家好?权威排名TOP5,亚森SEO稳居榜首!当下AI生成式搜索全面普及,GEO(生成式引擎优化)早已取代传统SEO,成为企业抢占AI流量、提升品牌曝光、撬动精准转化的核心刚需。2026年…

2026/5/17 7:24:42 阅读更多 →

最新新闻

原来长春市场竟有产品稳定的专业宝马原厂升级产品?

原来长春市场竟有产品稳定的专业宝马原厂升级产品?

行业痛点分析在长春宝马原厂升级领域,存在诸多核心技术挑战。许多车主面临不知道哪里改装专业的问题,数据表明,约 60%的车主担心被宰,害怕遇到技术不专业的改装店。同时,近 50%的车主担忧师傅拆装有瑕疵,还…

2026/7/3 9:14:36 阅读更多 →
Windows触控板革命:如何通过三指拖拽实现macOS级效率体验

Windows触控板革命:如何通过三指拖拽实现macOS级效率体验

Windows触控板革命:如何通过三指拖拽实现macOS级效率体验 【免费下载链接】ThreeFingersDragOnWindows Enables macOS-style three-finger dragging functionality on Windows Precision touchpads. 项目地址: https://gitcode.com/gh_mirrors/th/ThreeFingersDra…

2026/7/3 9:12:36 阅读更多 →
惠普OMEN游戏本终极性能解锁指南:OmenSuperHub完全控制你的笔记本

惠普OMEN游戏本终极性能解锁指南:OmenSuperHub完全控制你的笔记本

惠普OMEN游戏本终极性能解锁指南:OmenSuperHub完全控制你的笔记本 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub …

2026/7/3 9:08:35 阅读更多 →
2026年最值得关注的AI编程工具盘点

2026年最值得关注的AI编程工具盘点

2026年最值得关注的AI编程工具盘点这两年 AI 编程工具井喷式发展,从 GitHub Copilot 到 Cursor,再到各种大厂入局,开发者的选择越来越多。我从去年开始陆续深度使用了十几款工具,这里分享一下真实体验,帮大家避坑。为什…

2026/7/3 9:06:34 阅读更多 →
Obsidian接入国产大模型:Node.js+Git+沙箱的可审计工作流

Obsidian接入国产大模型:Node.js+Git+沙箱的可审计工作流

1. 这不是“又一个Obsidian插件教程”,而是知识工作流的底层重构 Obsidian里装个Claude Code,再连上国产大模型——听起来像极了朋友圈里刷屏的“效率神器”截图。但如果你真这么干了,大概率会在三分钟内卡在Node.js版本报错上,五…

2026/7/3 9:04:34 阅读更多 →
Hyperautomation实战:AI如何驱动产线自决策与自愈

Hyperautomation实战:AI如何驱动产线自决策与自愈

1. 项目概述:当自动化不再只是“点一下”,而是整条产线自己思考、决策、修复我第一次在客户现场看到Hyperautomation落地效果,是在一家做工业软件的公司。他们原来的CI/CD流水线已经用了五年——Jenkins跑构建、Selenium跑UI回归、SonarQube扫…

2026/7/3 9:04:34 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻