热门文章
最新发布
-
JuiceSSH安卓版 - 免费SSH连接工具 安全高效远程服务器管理 JuiceSSH:安卓端免费SSH连接工具,安全高效的远程管理神器 给大家推荐一款安卓设备专属的远程服务器管理工具——JuiceSSH!由拥有20年系统管理经验的Sonelli团队开发,凭借稳定的连接性能、全面的功能支持和优秀的用户体验,成为全球热门免费SSH客户端,每月新增用户超7.5万人,不管是系统管理员、开发者,还是需要远程管理服务器的用户,都能轻松满足需求! mjzpi1g3.png图片 一、核心功能:覆盖远程管理全场景需求 1. 稳定高效的连接能力 支持标准SSH协议,可实现远程登录、命令执行等基础操作,连接稳定无卡顿。 适配Mosh协议(移动优化SSH协议),即便在高延迟或网络不稳定的环境下,也能保持连接不中断,适配移动场景使用。 支持保存多个连接配置,包含主机名/IP地址、端口号、用户名及认证方式(密码或密钥),快速切换不同服务器,提升运维效率。 2. 灵活的端口转发与拓展功能 支持本地和远程端口转发,方便访问本地服务或进行开发调试,满足技术场景多样化需求。 集成Web浏览器,连接服务器后可直接在浏览器中打开相关网页,无需切换应用,操作更连贯。 兼容蓝牙、USB-OTG外接键盘,尤其对Asus Transformer系列设备的键盘 dock 适配良好,搭配自定义键盘映射(含Ctrl、Alt、箭头键等常用快捷键),移动端操作效率媲美电脑。 3. 安全同步与认证机制 内置CloudSync跨设备同步功能,所有连接配置与设置采用AES-256加密传输,保障数据安全,多台设备登录同一账户即可同步信息。 支持公钥认证与SSH密钥管理,可导入或生成SSH密钥,相比密码登录更安全,避免信息泄露风险。 二、核心特色:移动SSH工具的差异化优势 界面体验出色:采用现代化Holo风格UI,操作直观易懂;支持夜间模式,适配白天、夜间不同使用环境,视觉舒适度高。 兼容性广泛:支持Android 4.0及以上版本,适配Asus Transformer、Raspberry Pi等多种设备,老旧手机也能流畅运行。 持续迭代更新:开发团队保持稳定更新节奏,不断优化功能与兼容性,用户体验持续升级。 功能分级合理:免费版覆盖基础核心需求,Pro版解锁高级功能,满足不同用户的使用场景,无强制付费捆绑。 三、使用与收费说明 1. 简易操作流程 安装后打开应用,点击“连接→新建连接”,输入服务器相关信息(主机名/IP、端口、用户名、认证方式),保存后即可一键连接。 端口转发需在连接设置中添加本地或远程转发规则,同步功能需登录JuiceSSH账户后开启CloudSync即可生效。 2. 收费模式 免费版:包含基础SSH连接、本地端口转发、外部键盘支持等核心功能,满足日常基础使用。 Pro版(一次性购买):解锁远程端口转发、Web浏览器集成、CloudSync同步、去除广告等高级功能,具体价格以Google Play Store显示为准。 四、适用人群与场景 系统管理员:移动场景下远程运维服务器,处理紧急事务,无需依赖电脑,提升工作灵活性。 开发者:远程调试代码、访问开发环境,借助端口转发与浏览器集成功能,移动端也能高效开发。 技术学习者:学习SSH协议使用、远程服务器管理,免费版功能足够满足入门与实践需求。 有远程管理需求的普通用户:简单配置即可连接服务器,进行基础操作,无需专业技术背景。 app下载 JuiceSSH_3.2.2.zip 下载地址:https://pan.quark.cn/s/681c26dcf632 提取码: -
PyQt5 对话框控件:QDialog 与标准对话框(附登录实战代码) 第8篇:PyQt5对话框控件:QDialog与标准对话框(完整代码) 哈喽~ 欢迎来到PyQt5系列的第8篇!上一章我们掌握了QTextEdit(富文本)和QTableWidget(表格)的核心用法,今天聚焦对话框控件——对话框是PyQt5界面交互的“重要桥梁”,比如提示信息、选择文件、用户登录验证等场景都离不开它。我们会详细讲解两类对话框:标准对话框(系统预制,如消息框、文件选择框)和自定义对话框(基于QDialog开发专属交互窗口),全程搭配完整可运行代码,新手也能轻松掌握! mjzpc9v3.png图片 一、先明确:对话框的核心概念 在学习具体用法前,先理清对话框的两个核心属性,避免用错场景: 1. 模态(Modal)vs 非模态(Non-Modal) 模态对话框:弹出后阻塞主窗口操作,必须先处理对话框才能回到主窗口(如登录弹窗、确认删除提示),是最常用的类型; 非模态对话框:弹出后不阻塞主窗口,可同时操作主窗口和对话框(如悬浮的工具面板)。 2. 标准对话框 vs 自定义对话框 标准对话框:PyQt5预制的通用对话框(QMessageBox、QFileDialog、QColorDialog等),无需自定义界面,直接调用即可,开发效率高; 自定义对话框:基于QDialog类开发的专属对话框(如登录窗口、高级设置窗口),可自由设计界面和交互逻辑。 二、标准对话框详解:直接调用的通用交互窗口 PyQt5提供了一系列开箱即用的标准对话框,覆盖80%的通用交互场景,重点掌握以下5类: 1. QMessageBox:消息提示对话框(最常用) 用于显示提示、警告、错误、确认等信息,支持自定义按钮和交互逻辑。 效果图 信息提示框 - mjzoqu7y.png图片 警告提示框 - mjzos4d4.png图片 错误提示框 - mjzosqpr.png图片 确认提示框 - mjzot5q2.png图片 自定义提示框 - mjzp1z0h.png图片 完整代码:QMessageBox常用类型 import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QPushButton, QMessageBox ) class MessageBoxDemo(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("QMessageBox标准消息框演示") self.resize(400, 300) # 布局与按钮 layout = QVBoxLayout() layout.setSpacing(15) layout.setContentsMargins(50, 50, 50, 50) # 不同类型的消息框按钮 info_btn = QPushButton("信息提示框") warn_btn = QPushButton("警告提示框") error_btn = QPushButton("错误提示框") question_btn = QPushButton("确认对话框") custom_btn = QPushButton("自定义按钮对话框") # 绑定信号 info_btn.clicked.connect(self.show_info) warn_btn.clicked.connect(self.show_warn) error_btn.clicked.connect(self.show_error) question_btn.clicked.connect(self.show_question) custom_btn.clicked.connect(self.show_custom) # 添加到布局 for btn in [info_btn, warn_btn, error_btn, question_btn, custom_btn]: layout.addWidget(btn) self.setLayout(layout) # 1. 信息提示框(仅提示,无返回值) def show_info(self): QMessageBox.information( self, # 父窗口 "信息", # 标题 "操作成功!这是一个信息提示框。", # 内容 QMessageBox.Ok # 按钮(默认Ok) ) # 2. 警告提示框 def show_warn(self): QMessageBox.warning( self, "警告", "数据未保存,关闭窗口将丢失内容!", QMessageBox.Ok | QMessageBox.Cancel # 多个按钮 ) # 3. 错误提示框 def show_error(self): QMessageBox.critical( self, "错误", "文件读取失败,请检查文件路径是否正确!", QMessageBox.Retry | QMessageBox.Abort ) # 4. 确认对话框(带返回值,判断用户选择) def show_question(self): reply = QMessageBox.question( self, "确认", "确定要删除这条数据吗?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, # 按钮组合 QMessageBox.No # 默认选中No按钮 ) # 判断用户点击的按钮 if reply == QMessageBox.Yes: print("用户选择:删除") elif reply == QMessageBox.No: print("用户选择:不删除") else: print("用户选择:取消") # 5. 自定义按钮对话框 def show_custom(self): # 创建自定义消息框 msg_box = QMessageBox(self) msg_box.setWindowTitle("自定义对话框") msg_box.setText("请选择操作:") # 设置自定义按钮 btn1 = msg_box.addButton("导出", QMessageBox.ActionRole) btn2 = msg_box.addButton("导入", QMessageBox.ActionRole) btn3 = msg_box.addButton("取消", QMessageBox.CancelRole) # 显示对话框并获取返回值 msg_box.exec_() # 判断用户点击的按钮 if msg_box.clickedButton() == btn1: print("用户选择:导出") elif msg_box.clickedButton() == btn2: print("用户选择:导入") else: print("用户选择:取消") if __name__ == "__main__": app = QApplication(sys.argv) window = MessageBoxDemo() window.show() sys.exit(app.exec_())QMessageBox核心要点 常用类型:information()(信息)、warning()(警告)、critical()(错误)、question()(确认); 按钮组合:用|拼接(如QMessageBox.Yes | QMessageBox.No); 返回值判断:通过返回的枚举值(如QMessageBox.Yes)判断用户操作; 自定义按钮:创建QMessageBox实例,用addButton()添加自定义按钮。 2. 其他标准对话框:文件/颜色/字体选择 除了消息框,PyQt5还提供了文件、颜色、字体选择的标准对话框,用法统一且简单: 完整代码:文件/颜色/字体对话框 效果如图 mjzp4re8.png图片 import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QPushButton, QFileDialog, QColorDialog, QFontDialog, QLabel ) from PyQt5.QtGui import QColor, QFont from PyQt5.QtCore import Qt class StandardDialogsDemo(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("标准对话框(文件/颜色/字体)演示") self.resize(500, 300) # 布局 layout = QVBoxLayout() layout.setSpacing(15) layout.setContentsMargins(50, 50, 50, 50) # 按钮 file_btn = QPushButton("选择文件") color_btn = QPushButton("选择颜色") font_btn = QPushButton("选择字体") # 结果显示标签 self.result_label = QLabel("选择结果将显示在这里...") self.result_label.setAlignment(Qt.AlignCenter) # 绑定信号 file_btn.clicked.connect(self.choose_file) color_btn.clicked.connect(self.choose_color) font_btn.clicked.connect(self.choose_font) # 添加到布局 layout.addWidget(file_btn) layout.addWidget(color_btn) layout.addWidget(font_btn) layout.addWidget(self.result_label) self.setLayout(layout) # 1. 文件选择对话框(打开文件) def choose_file(self): # getOpenFileName:选择单个文件 # getOpenFileNames:选择多个文件 # getSaveFileName:保存文件 file_path, _ = QFileDialog.getOpenFileName( self, # 父窗口 "选择文件", # 标题 "", # 默认路径(当前目录) "Text Files (*.txt);;Image Files (*.png *.jpg);;All Files (*.*)" # 文件筛选器 ) if file_path: self.result_label.setText(f"选中文件:{file_path}") else: self.result_label.setText("未选择任何文件") # 2. 颜色选择对话框 def choose_color(self): # 获取当前标签颜色,作为默认颜色 current_color = self.result_label.textColor() # 弹出颜色选择框 color = QColorDialog.getColor( current_color, # 默认颜色 self, "选择颜色" ) if color.isValid(): # 用户选择了有效颜色 self.result_label.setText(f"选中颜色:{color.name()}") self.result_label.setStyleSheet(f"color: {color.name()}; font-size: 16px;") # 3. 字体选择对话框 def choose_font(self): # 获取当前标签字体,作为默认字体 current_font = self.result_label.font() # 弹出字体选择框 font, ok = QFontDialog.getFont( current_font, # 默认字体 self, "选择字体" ) if ok: # 用户确认选择 self.result_label.setText(f"选中字体:{font.family()},大小:{font.pointSize()}") self.result_label.setFont(font) if __name__ == "__main__": app = QApplication(sys.argv) window = StandardDialogsDemo() window.show() sys.exit(app.exec_())核心方法总结 对话框类型核心方法关键参数/返回值QFileDialoggetOpenFileName()返回(选中路径, 筛选器),支持多文件选择(getOpenFileNames)QColorDialoggetColor()返回QColor对象,isValid()判断是否选择有效颜色QFontDialoggetFont()返回(字体对象, 是否确认),ok为True时表示用户确认选择三、自定义对话框:基于QDialog开发专属交互窗口 当标准对话框无法满足需求时(如登录验证、高级参数设置),需要基于QDialog开发自定义对话框,核心是“设计界面+处理返回值+设置模态”。 1. 自定义对话框基础:登录窗口案例 实现一个带“用户名/密码输入+登录/取消按钮”的登录对话框,支持模态显示和返回值判断: 步骤1:自定义登录对话框类 # login_dialog.py(可单独文件,也可写在主文件) from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox ) from PyQt5.QtCore import Qt class LoginDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.init_ui() # 设置模态(默认模态,也可显式设置) self.setModal(True) def init_ui(self): # 对话框基础设置 self.setWindowTitle("用户登录") self.setFixedSize(350, 200) # 固定大小,避免缩放 # 布局 layout = QVBoxLayout() layout.setSpacing(15) layout.setContentsMargins(40, 30, 40, 30) # 用户名输入 user_layout = QHBoxLayout() user_layout.addWidget(QLabel("用户名:")) self.user_edit = QLineEdit() self.user_edit.setPlaceholderText("请输入用户名") user_layout.addWidget(self.user_edit) # 密码输入 pwd_layout = QHBoxLayout() pwd_layout.addWidget(QLabel("密 码:")) self.pwd_edit = QLineEdit() self.pwd_edit.setEchoMode(QLineEdit.Password) # 密码隐藏 self.pwd_edit.setPlaceholderText("请输入密码") pwd_layout.addWidget(self.pwd_edit) # 按钮区 btn_layout = QHBoxLayout() login_btn = QPushButton("登录") cancel_btn = QPushButton("取消") login_btn.clicked.connect(self.check_login) cancel_btn.clicked.connect(self.reject) # 关闭对话框,返回Rejected btn_layout.addWidget(login_btn) btn_layout.addWidget(cancel_btn) # 添加到布局 layout.addLayout(user_layout) layout.addLayout(pwd_layout) layout.addLayout(btn_layout) self.setLayout(layout) def check_login(self): """验证登录信息""" username = self.user_edit.text().strip() password = self.pwd_edit.text().strip() # 简单验证(实际项目中对接数据库/接口) if username == "admin" and password == "123456": # 验证通过,关闭对话框并返回Accepted self.accept() else: QMessageBox.warning( self, "登录失败", "用户名或密码错误!", QMessageBox.Ok ) # 可选:获取用户输入的信息(供主窗口调用) def get_user_info(self): return { "username": self.user_edit.text().strip(), "password": self.pwd_edit.text().strip() }步骤2:主窗口调用自定义登录对话框 import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QPushButton, QLabel ) from login_dialog import LoginDialog # 若在同一文件,无需导入 class MainWindow(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("主窗口(调用自定义登录对话框)") self.resize(400, 300) # 布局 layout = QVBoxLayout() layout.setSpacing(20) layout.setContentsMargins(50, 50, 50, 50) # 按钮和标签 login_btn = QPushButton("点击登录") self.status_label = QLabel("当前状态:未登录") self.status_label.setAlignment(Qt.AlignCenter) # 绑定信号 login_btn.clicked.connect(self.show_login_dialog) # 添加到布局 layout.addWidget(login_btn) layout.addWidget(self.status_label) self.setLayout(layout) def show_login_dialog(self): """显示登录对话框并处理返回值""" # 创建登录对话框实例 login_dlg = LoginDialog(self) # 显示对话框并获取返回值 result = login_dlg.exec_() # 判断返回值:Accepted(登录成功)/ Rejected(取消/关闭) if result == login_dlg.Accepted: user_info = login_dlg.get_user_info() self.status_label.setText(f"当前状态:已登录(用户名:{user_info['username']})") else: self.status_label.setText("当前状态:取消登录") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())2. 自定义对话框核心要点 继承QDialog:自定义对话框必须继承QDialog类; 模态设置:setModal(True)设置模态(默认模态),非模态用setModal(False); 返回值处理: self.accept():关闭对话框,返回QDialog.Accepted(表示操作成功); self.reject():关闭对话框,返回QDialog.Rejected(表示取消/失败); 调用exec_()显示对话框,返回值为Accepted/Rejected; 数据传递:通过自定义方法(如get_user_info())将对话框内的输入数据传递给主窗口; 窗口大小:自定义对话框建议用setFixedSize()固定大小,避免用户缩放导致界面混乱。 四、综合案例:整合标准对话框与自定义对话框 实现一个“简易文本编辑器”,整合: 自定义登录对话框(启动时要求登录); 标准文件对话框(打开/保存文件); 标准颜色/字体对话框(设置文本样式); 标准消息框(提示操作结果)。 完整代码 mjzp8xp5.png图片 mjzp9112.png图片 import sys import os from PyQt5.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QTextEdit, QFileDialog, QColorDialog, QFontDialog, QMessageBox, QDialog, QLabel, QLineEdit ) from PyQt5.QtGui import QColor, QFont from PyQt5.QtCore import Qt # 自定义登录对话框 class LoginDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.init_ui() self.setModal(True) def init_ui(self): self.setWindowTitle("用户登录") self.setFixedSize(350, 200) layout = QVBoxLayout() layout.setSpacing(15) layout.setContentsMargins(40, 30, 40, 30) # 用户名 user_layout = QHBoxLayout() user_layout.addWidget(QLabel("用户名:")) self.user_edit = QLineEdit() self.user_edit.setPlaceholderText("admin") user_layout.addWidget(self.user_edit) layout.addLayout(user_layout) # 密码 pwd_layout = QHBoxLayout() pwd_layout.addWidget(QLabel("密 码:")) self.pwd_edit = QLineEdit() self.pwd_edit.setEchoMode(QLineEdit.Password) self.pwd_edit.setPlaceholderText("123456") pwd_layout.addWidget(self.pwd_edit) layout.addLayout(pwd_layout) # 按钮 btn_layout = QHBoxLayout() login_btn = QPushButton("登录") cancel_btn = QPushButton("取消") login_btn.clicked.connect(self.check_login) cancel_btn.clicked.connect(self.reject) btn_layout.addWidget(login_btn) btn_layout.addWidget(cancel_btn) layout.addLayout(btn_layout) self.setLayout(layout) def check_login(self): if self.user_edit.text().strip() == "admin" and self.pwd_edit.text().strip() == "123456": self.accept() else: QMessageBox.warning(self, "失败", "用户名/密码错误!") # 主编辑器窗口 class EditorWindow(QWidget): def __init__(self): super().__init__() # 先显示登录对话框,验证失败则退出 if not self.check_login(): sys.exit() # 初始化主界面 self.init_ui() self.current_file = None def check_login(self): """显示登录对话框,返回是否登录成功""" login_dlg = LoginDialog(self) return login_dlg.exec_() == login_dlg.Accepted def init_ui(self): self.setWindowTitle("简易编辑器(整合对话框)") self.resize(800, 600) # 布局 main_layout = QVBoxLayout() main_layout.setSpacing(10) main_layout.setContentsMargins(15, 15, 15, 15) # 功能按钮区 btn_layout = QHBoxLayout() open_btn = QPushButton("打开文件") save_btn = QPushButton("保存文件") color_btn = QPushButton("字体颜色") font_btn = QPushButton("字体设置") for btn in [open_btn, save_btn, color_btn, font_btn]: btn.setFixedSize(100, 30) btn_layout.addWidget(open_btn) btn_layout.addWidget(save_btn) btn_layout.addStretch() btn_layout.addWidget(color_btn) btn_layout.addWidget(font_btn) # 文本编辑区 self.text_edit = QTextEdit() self.text_edit.setFont(QFont("微软雅黑", 12)) # 添加到布局 main_layout.addLayout(btn_layout) main_layout.addWidget(self.text_edit) self.setLayout(main_layout) # 绑定信号 open_btn.clicked.connect(self.open_file) save_btn.clicked.connect(self.save_file) color_btn.clicked.connect(self.set_font_color) font_btn.clicked.connect(self.set_font) # 打开文件(标准文件对话框) def open_file(self): file_path, _ = QFileDialog.getOpenFileName( self, "打开文件", "", "Text Files (*.txt);;All Files (*.*)" ) if file_path and os.path.exists(file_path): with open(file_path, "r", encoding="utf-8") as f: self.text_edit.setText(f.read()) self.current_file = file_path QMessageBox.information(self, "成功", f"已打开文件:{os.path.basename(file_path)}") # 保存文件(标准文件对话框) def save_file(self): if self.current_file: with open(self.current_file, "w", encoding="utf-8") as f: f.write(self.text_edit.toPlainText()) QMessageBox.information(self, "成功", "文件保存成功!") else: file_path, _ = QFileDialog.getSaveFileName( self, "保存文件", "", "Text Files (*.txt)" ) if file_path: if not file_path.endswith(".txt"): file_path += ".txt" with open(file_path, "w", encoding="utf-8") as f: f.write(self.text_edit.toPlainText()) self.current_file = file_path QMessageBox.information(self, "成功", f"文件已保存到:{file_path}") # 设置字体颜色(标准颜色对话框) def set_font_color(self): color = QColorDialog.getColor(Qt.black, self, "选择字体颜色") if color.isValid(): fmt = self.text_edit.currentCharFormat() fmt.setForeground(color) self.text_edit.mergeCurrentCharFormat(fmt) # 设置字体(标准字体对话框) def set_font(self): font, ok = QFontDialog.getFont(self.text_edit.font(), self, "选择字体") if ok: self.text_edit.setCurrentFont(font) if __name__ == "__main__": app = QApplication(sys.argv) window = EditorWindow() window.show() sys.exit(app.exec_())五、常见问题排查 1. 对话框相关问题 问题1:自定义对话框非模态,主窗口可操作 → 解决:调用setModal(True),或用exec_()显示(show()显示为非模态); 问题2:文件对话框选择中文路径乱码 → 解决:读写文件时指定encoding="utf-8",Windows系统可尝试encoding="gbk"; 问题3:登录对话框关闭后主窗口也退出 → 解决:主窗口初始化时,登录失败调用sys.exit()需确保是在app创建后; 问题4:标准对话框标题/按钮显示英文 → 解决:PyQt5默认是英文,可通过设置Qt的语言环境(需额外配置翻译文件),或使用自定义对话框替换。 2. 模态对话框的坑 exec_():显示模态对话框,阻塞主线程,返回值为Accepted/Rejected; show():显示非模态对话框,不阻塞主线程,无返回值; 自定义对话框若用show()显示,需手动设置setModal(True)才能变为模态。 总结 标准对话框:PyQt5预制的通用交互窗口(消息框、文件选择框等),直接调用即可,覆盖80%通用场景; 自定义对话框:继承QDialog开发专属窗口,核心是setModal()设置模态、accept()/reject()处理返回值; 模态vs非模态:模态对话框阻塞主窗口(常用),非模态不阻塞(适合悬浮面板); 综合应用:实际项目中常结合标准对话框和自定义对话框,比如登录验证+文件操作+消息提示。 下一章我们将学习PyQt5的容器控件(QTabWidget、QGroupBox),实现多标签页、分组管理的复杂界面,进一步提升界面的层次感和实用性。如果在对话框开发中遇到问题,或者想拓展更复杂的自定义对话框(如带验证码的登录窗口),欢迎在评论区留言讨论~ -
全新IP定位系统源码 这儿存在一款全新的IP定位系统源码,并且它是全开源还具轻量化特点的,它是借助经纬度来开展解析定位的,其精度需自行去进行测试,它适合二次开发,喜爱它的人自行去部署吧! 安装说明 后台登录的位置是,http://你的域名/admin.php 后台的默认账号是admin 后台的默认密码是www.tfbkw.com 管理员账号密码在login.php里边的第十六行,第十七行进行替换 API Key申请的地址是,https://console.amap.com ,要把申请到的key去到文件process_location.php的第6行,去到admin/index.php的第35行,去把自己的key用来替换 。 20260103223022954-1-1024x556.webp图片 20260103223031589-2.webp图片 全新IP定位系统源码 下载地址:https://www.123912.com/s/7zXJjv-9uR23 提取码: -
最新APP导航下载页系统源码 – 带后台 一款颜值超高的App导航推荐页源码来袭,它配备后台,属于PHP源码,采用Thinkphp框架。此源码安装轻松又简洁,在后台添加应用和轮播广告也十分便利。网站能同时自适应PC端与手机端。有意者可自行部署哟! 20260102221109794-1-1024x558.webp图片 20260102221114253-2-1024x677.webp图片 20260102221121916-3-1024x483.webp图片 20260102221152630-6-1024x480.webp图片 安装说明 上传源码到根目录,伪静态改为:thinkphp php 版本 5.6-7.2(本人测的 5.6) 导入数据库文件,修改数据库路径Application/Common/Conf/config.php 后台路径: 域名/Youni 后台账号:admin 后台密码:123456 最新APP导航下载页系统源码 – 带后台 下载地址:https://pan.quark.cn/s/578fff49d795 提取码: -
PyQt5文本与表格控件:QTextEdit与QTableWidget(附实战代码) 第7篇:PyQt5文本与表格控件:QTextEdit与QTableWidget(完整代码) 哈喽~ 欢迎来到PyQt5系列的第7篇!上一章我们掌握了网格布局和表单布局,解决了复杂界面的排版问题。今天我们聚焦两个高频实用控件:QTextEdit(多行富文本编辑控件)和QTableWidget(表格控件)——这两个控件是处理“大段文本”和“结构化数据”的核心,比如文本编辑器、数据管理系统、报表展示等场景都离不开它们。全程搭配完整可运行代码,新手也能轻松掌握! mjxm4a2v.png图片 一、先明确:两个控件的核心定位 在学习具体用法前,先理清这两个控件的适用场景,避免用错: QTextEdit:多行文本编辑/展示控件,支持富文本(字体、颜色、图片、超链接),比QLineEdit(单行)功能强大,核心用于“大段文本处理”(如记事本、富文本编辑器); QTableWidget:表格控件,支持行/列的增删改查、单元格编辑、数据排序,核心用于“结构化数据展示/编辑”(如Excel简易表格、用户信息列表)。 二、QTextEdit详解:从基础文本到富文本编辑 QTextEdit是阶段一“简易记事本”中用到的核心控件,但当时只用到了基础文本功能,这一节我们深挖它的富文本能力。 1. QTextEdit基础用法(完整代码) 先回顾基础功能,再拓展富文本设置: import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QTextEdit, QVBoxLayout, QPushButton, QHBoxLayout, QColorDialog, QFontDialog ) from PyQt5.QtGui import QTextCharFormat, QFont, QColor from PyQt5.QtCore import Qt class TextEditDemo(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("QTextEdit基础与富文本演示") self.resize(600, 400) # 1. 主布局(垂直):按钮区 + 文本编辑区 main_layout = QVBoxLayout() main_layout.setSpacing(10) main_layout.setContentsMargins(15, 15, 15, 15) # 2. 功能按钮区(水平布局) btn_layout = QHBoxLayout() btn_layout.setSpacing(8) # 富文本功能按钮 self.bold_btn = QPushButton("加粗") self.italic_btn = QPushButton("斜体") self.color_btn = QPushButton("字体颜色") self.font_btn = QPushButton("选择字体") self.clear_btn = QPushButton("清空文本") # 按钮样式 btn_size = (80, 30) for btn in [self.bold_btn, self.italic_btn, self.color_btn, self.font_btn, self.clear_btn]: btn.setFixedSize(*btn_size) # 添加到按钮布局 btn_layout.addWidget(self.bold_btn) btn_layout.addWidget(self.italic_btn) btn_layout.addWidget(self.color_btn) btn_layout.addWidget(self.font_btn) btn_layout.addStretch() # 伸缩空间 btn_layout.addWidget(self.clear_btn) # 3. 创建QTextEdit控件 self.text_edit = QTextEdit() # 基础设置:默认提示文本、字体 self.text_edit.setPlaceholderText("请输入文本(支持富文本格式:加粗、斜体、改颜色等)") self.text_edit.setFont(QFont("微软雅黑", 12)) # 允许自动换行 self.text_edit.setLineWrapMode(QTextEdit.WidgetWidth) # 4. 添加到主布局 main_layout.addLayout(btn_layout) main_layout.addWidget(self.text_edit) # 5. 绑定布局和信号 self.setLayout(main_layout) self.bind_signals() def bind_signals(self): """绑定信号与槽""" self.bold_btn.clicked.connect(self.set_bold) self.italic_btn.clicked.connect(self.set_italic) self.color_btn.clicked.connect(self.set_font_color) self.font_btn.clicked.connect(self.choose_font) self.clear_btn.clicked.connect(self.text_edit.clear) def set_bold(self): """设置选中文本加粗/取消加粗""" # 获取当前光标选中的文本格式 fmt = QTextCharFormat() # 切换加粗状态:当前加粗则取消,反之则加粗 fmt.setFontWeight(QFont.Bold if self.text_edit.fontWeight() != QFont.Bold else QFont.Normal) # 应用格式到选中文本 self.text_edit.mergeCurrentCharFormat(fmt) def set_italic(self): """设置选中文本斜体/取消斜体""" fmt = QTextCharFormat() fmt.setFontItalic(not self.text_edit.fontItalic()) self.text_edit.mergeCurrentCharFormat(fmt) def set_font_color(self): """选择字体颜色并应用到选中文本""" # 弹出颜色选择对话框 color = QColorDialog.getColor(Qt.black, self, "选择字体颜色") if color.isValid(): # 用户选择了有效颜色 fmt = QTextCharFormat() fmt.setForeground(color) self.text_edit.mergeCurrentCharFormat(fmt) def choose_font(self): """选择字体(字体名、大小、样式)""" # 弹出字体选择对话框 font, ok = QFontDialog.getFont(self.text_edit.font(), self, "选择字体") if ok: # 用户确认选择 self.text_edit.setCurrentFont(font) if __name__ == "__main__": app = QApplication(sys.argv) window = TextEditDemo() window.show() sys.exit(app.exec_())2. QTextEdit核心方法解析 QTextEdit的核心分为“文本操作”和“格式设置”两类,重点掌握以下方法: (1)基础文本操作 方法作用toPlainText()获取纯文本内容(忽略富文本格式)setPlainText(文本)设置纯文本内容(覆盖原有内容)toHtml()获取富文本内容(HTML格式)setHtml(HTML文本)设置富文本内容(支持HTML标签)append(文本)在末尾追加文本(保留原有格式)clear()清空所有文本undo()/redo()撤销/重做操作(2)富文本格式设置 方法作用mergeCurrentCharFormat(格式对象)将格式应用到选中的文本setCurrentFont(字体对象)设置当前光标位置/选中文本的字体setFontWeight(QFont.Bold/Normal)设置加粗/取消加粗setFontItalic(True/False)设置斜体/取消斜体setForeground(QColor)设置字体颜色3. QTextEdit实战:简易富文本编辑器 基于基础用法,拓展一个带“打开/保存富文本”功能的编辑器,支持保存为HTML格式(保留富文本样式): import sys import os from PyQt5.QtWidgets import ( QApplication, QWidget, QTextEdit, QVBoxLayout, QPushButton, QHBoxLayout, QColorDialog, QFontDialog, QFileDialog ) from PyQt5.QtGui import QTextCharFormat, QFont, QColor from PyQt5.QtCore import Qt class RichTextEditor(QWidget): def __init__(self): super().__init__() self.init_ui() self.current_file_path = None # 记录当前文件路径 def init_ui(self): self.setWindowTitle("简易富文本编辑器") self.resize(800, 600) # 1. 主布局 main_layout = QVBoxLayout() main_layout.setSpacing(10) main_layout.setContentsMargins(15, 15, 15, 15) # 2. 顶部功能按钮区 top_btn_layout = QHBoxLayout() self.new_btn = QPushButton("新建") self.open_btn = QPushButton("打开") self.save_btn = QPushButton("保存") for btn in [self.new_btn, self.open_btn, self.save_btn]: btn.setFixedSize(80, 30) top_btn_layout.addWidget(self.new_btn) top_btn_layout.addWidget(self.open_btn) top_btn_layout.addWidget(self.save_btn) top_btn_layout.addStretch() # 3. 格式设置按钮区 fmt_btn_layout = QHBoxLayout() self.bold_btn = QPushButton("加粗") self.italic_btn = QPushButton("斜体") self.color_btn = QPushButton("字体颜色") self.font_btn = QPushButton("选择字体") for btn in [self.bold_btn, self.italic_btn, self.color_btn, self.font_btn]: btn.setFixedSize(80, 30) fmt_btn_layout.addWidget(self.bold_btn) fmt_btn_layout.addWidget(self.italic_btn) fmt_btn_layout.addWidget(self.color_btn) fmt_btn_layout.addWidget(self.font_btn) fmt_btn_layout.addStretch() # 4. 文本编辑区 self.text_edit = QTextEdit() self.text_edit.setFont(QFont("微软雅黑", 12)) # 5. 添加到主布局 main_layout.addLayout(top_btn_layout) main_layout.addLayout(fmt_btn_layout) main_layout.addWidget(self.text_edit) # 6. 绑定布局和信号 self.setLayout(main_layout) self.bind_signals() def bind_signals(self): """绑定所有信号与槽""" # 文件操作 self.new_btn.clicked.connect(self.on_new) self.open_btn.clicked.connect(self.on_open) self.save_btn.clicked.connect(self.on_save) # 格式操作 self.bold_btn.clicked.connect(self.set_bold) self.italic_btn.clicked.connect(self.set_italic) self.color_btn.clicked.connect(self.set_font_color) self.font_btn.clicked.connect(self.choose_font) # ---------- 文件操作槽函数 ---------- def on_new(self): """新建文件:清空文本,重置路径""" self.text_edit.clear() self.current_file_path = None self.setWindowTitle("简易富文本编辑器 - 未保存文件") def on_open(self): """打开文件:支持txt(纯文本)和html(富文本)""" file_path, _ = QFileDialog.getOpenFileName( self, "打开文件", "", "HTML Files (*.html);;Text Files (*.txt);;All Files (*.*)" ) if file_path and os.path.exists(file_path): self.current_file_path = file_path # 根据后缀选择读取方式 if file_path.endswith(".html"): with open(file_path, "r", encoding="utf-8") as f: content = f.read() self.text_edit.setHtml(content) else: with open(file_path, "r", encoding="utf-8") as f: content = f.read() self.text_edit.setPlainText(content) # 更新窗口标题 self.setWindowTitle(f"简易富文本编辑器 - {os.path.basename(file_path)}") def on_save(self): """保存文件:默认保存为HTML(保留富文本格式)""" if self.current_file_path: # 直接保存 self.save_file(self.current_file_path) else: # 弹出保存对话框 file_path, _ = QFileDialog.getSaveFileName( self, "保存文件", "", "HTML Files (*.html);;Text Files (*.txt)" ) if file_path: # 补充后缀 if not (file_path.endswith(".html") or file_path.endswith(".txt")): file_path += ".html" self.save_file(file_path) self.current_file_path = file_path self.setWindowTitle(f"简易富文本编辑器 - {os.path.basename(file_path)}") def save_file(self, file_path): """辅助函数:保存文件""" if file_path.endswith(".html"): content = self.text_edit.toHtml() else: content = self.text_edit.toPlainText() with open(file_path, "w", encoding="utf-8") as f: f.write(content) # ---------- 格式设置槽函数 ---------- def set_bold(self): fmt = QTextCharFormat() fmt.setFontWeight(QFont.Bold if self.text_edit.fontWeight() != QFont.Bold else QFont.Normal) self.text_edit.mergeCurrentCharFormat(fmt) def set_italic(self): fmt = QTextCharFormat() fmt.setFontItalic(not self.text_edit.fontItalic()) self.text_edit.mergeCurrentCharFormat(fmt) def set_font_color(self): color = QColorDialog.getColor(Qt.black, self, "选择字体颜色") if color.isValid(): fmt = QTextCharFormat() fmt.setForeground(color) self.text_edit.mergeCurrentCharFormat(fmt) def choose_font(self): font, ok = QFontDialog.getFont(self.text_edit.font(), self, "选择字体") if ok: self.text_edit.setCurrentFont(font) if __name__ == "__main__": app = QApplication(sys.argv) editor = RichTextEditor() editor.show() sys.exit(app.exec_())三、QTableWidget详解:结构化数据的展示与编辑 QTableWidget是处理表格数据的核心控件,支持行/列管理、单元格编辑、数据排序,是实现“数据表格”的首选。 1. QTableWidget基础用法(完整代码) 先实现一个基础表格,演示行/列添加、单元格赋值、选中行获取等核心操作: import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QHBoxLayout, QPushButton, QMessageBox ) from PyQt5.QtCore import Qt class TableWidgetDemo(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("QTableWidget基础演示") self.resize(600, 400) # 1. 主布局:按钮区 + 表格区 main_layout = QVBoxLayout() main_layout.setSpacing(15) main_layout.setContentsMargins(15, 15, 15, 15) # 2. 功能按钮区 btn_layout = QHBoxLayout() self.add_row_btn = QPushButton("添加行") self.del_row_btn = QPushButton("删除选中行") self.get_data_btn = QPushButton("获取选中行数据") self.clear_btn = QPushButton("清空表格") for btn in [self.add_row_btn, self.del_row_btn, self.get_data_btn, self.clear_btn]: btn.setFixedSize(100, 30) btn_layout.addWidget(self.add_row_btn) btn_layout.addWidget(self.del_row_btn) btn_layout.addWidget(self.get_data_btn) btn_layout.addWidget(self.clear_btn) btn_layout.addStretch() # 3. 创建QTableWidget控件 self.table = QTableWidget() # 设置表格行列数:5行4列 self.table.setRowCount(5) self.table.setColumnCount(4) # 设置列标题 self.table.setHorizontalHeaderLabels(["ID", "姓名", "性别", "年龄"]) # 可选设置:列宽自适应、行高自适应、禁止编辑(默认允许) self.table.horizontalHeader().setStretchLastSection(True) # 最后一列拉伸 self.table.verticalHeader().setVisible(False) # 隐藏行号 # self.table.setEditTriggers(QTableWidget.NoEditTriggers) # 禁止编辑单元格 # 4. 填充初始数据 init_data = [ [1, "张三", "男", 25], [2, "李四", "女", 28], [3, "王五", "男", 30], [4, "赵六", "女", 22], [5, "钱七", "男", 27] ] for row in range(len(init_data)): for col in range(len(init_data[row])): # 创建表格项(设置居中对齐) item = QTableWidgetItem(str(init_data[row][col])) item.setTextAlignment(Qt.AlignCenter) # 将项添加到表格 self.table.setItem(row, col, item) # 5. 添加到主布局 main_layout.addLayout(btn_layout) main_layout.addWidget(self.table) # 6. 绑定布局和信号 self.setLayout(main_layout) self.bind_signals() def bind_signals(self): """绑定信号与槽""" self.add_row_btn.clicked.connect(self.add_row) self.del_row_btn.clicked.connect(self.del_selected_row) self.get_data_btn.clicked.connect(self.get_selected_data) self.clear_btn.clicked.connect(self.clear_table) def add_row(self): """添加一行空数据""" # 获取当前行数,在末尾添加新行 current_row = self.table.rowCount() self.table.insertRow(current_row) # 给新行ID列赋值(自增) id_item = QTableWidgetItem(str(current_row + 1)) id_item.setTextAlignment(Qt.AlignCenter) self.table.setItem(current_row, 0, id_item) def del_selected_row(self): """删除选中的行""" # 获取选中的行号(单个选中) selected_rows = self.table.selectedItems() if not selected_rows: QMessageBox.warning(self, "提示", "请先选中要删除的行!") return # 获取选中行的行号(取第一个选中项的行号) row = selected_rows[0].row() self.table.removeRow(row) def get_selected_data(self): """获取选中行的所有数据""" selected_rows = self.table.selectedItems() if not selected_rows: QMessageBox.warning(self, "提示", "请先选中一行!") return # 提取选中行的所有列数据 row = selected_rows[0].row() data = [] for col in range(self.table.columnCount()): item = self.table.item(row, col) data.append(item.text() if item else "") # 显示数据 QMessageBox.information(self, "选中行数据", f"ID:{data[0]}\n姓名:{data[1]}\n性别:{data[2]}\n年龄:{data[3]}") def clear_table(self): """清空表格(保留列标题)""" self.table.setRowCount(0) if __name__ == "__main__": app = QApplication(sys.argv) window = TableWidgetDemo() window.show() sys.exit(app.exec_())2. QTableWidget核心方法解析 QTableWidget的核心围绕“行/列管理”和“单元格操作”,重点掌握: (1)行列管理 方法作用setRowCount(行数)设置表格行数setColumnCount(列数)设置表格列数setHorizontalHeaderLabels([列标题列表])设置列标题insertRow(行号)在指定行号位置插入新行removeRow(行号)删除指定行setRowCount(0)清空所有行(保留列标题)(2)单元格操作 方法作用setItem(行号, 列号, QTableWidgetItem)给指定单元格设置内容item(行号, 列号)获取指定单元格的项selectedItems()获取所有选中的单元格项setEditTriggers(触发方式)设置单元格编辑触发方式(如NoEditTriggers禁止编辑)setTextAlignment(对齐方式)设置单元格文本对齐(如Qt.AlignCenter居中)(3)样式/布局优化 方法作用horizontalHeader().setStretchLastSection(True)最后一列自适应拉伸verticalHeader().setVisible(False)隐藏行号setColumnWidth(列号, 宽度)设置指定列的宽度setRowHeight(行号, 高度)设置指定行的高度3. QTableWidget实战:简易数据表格管理器 拓展一个带“导入/导出数据”(CSV格式)、“数据排序”功能的表格管理器,贴合实际数据管理场景: import sys import os import csv from PyQt5.QtWidgets import ( QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QHBoxLayout, QPushButton, QMessageBox, QFileDialog, QComboBox ) from PyQt5.QtCore import Qt class TableManager(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("简易数据表格管理器") self.resize(700, 500) # 1. 主布局 main_layout = QVBoxLayout() main_layout.setSpacing(15) main_layout.setContentsMargins(15, 15, 15, 15) # 2. 顶部功能区(导入/导出 + 排序) top_layout = QHBoxLayout() # 导入/导出按钮 self.import_btn = QPushButton("导入CSV") self.export_btn = QPushButton("导出CSV") # 排序下拉框 self.sort_combo = QComboBox() self.sort_combo.addItems(["按ID升序", "按年龄升序", "按年龄降序"]) self.sort_btn = QPushButton("排序") # 样式设置 for btn in [self.import_btn, self.export_btn, self.sort_btn]: btn.setFixedSize(100, 30) self.sort_combo.setFixedWidth(120) # 添加到布局 top_layout.addWidget(self.import_btn) top_layout.addWidget(self.export_btn) top_layout.addStretch() top_layout.addWidget(self.sort_combo) top_layout.addWidget(self.sort_btn) # 3. 表格区 self.table = QTableWidget() # 初始列标题 self.table.setColumnCount(4) self.table.setHorizontalHeaderLabels(["ID", "姓名", "性别", "年龄"]) # 布局优化 self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) # 4. 添加到主布局 main_layout.addLayout(top_layout) main_layout.addWidget(self.table) # 5. 绑定信号 self.setLayout(main_layout) self.bind_signals() def bind_signals(self): self.import_btn.clicked.connect(self.import_csv) self.export_btn.clicked.connect(self.export_csv) self.sort_btn.clicked.connect(self.sort_data) # ---------- CSV导入导出 ---------- def import_csv(self): """导入CSV文件到表格""" file_path, _ = QFileDialog.getOpenFileName( self, "导入CSV文件", "", "CSV Files (*.csv);;All Files (*.*)" ) if not file_path: return try: # 清空原有数据 self.table.setRowCount(0) # 读取CSV文件 with open(file_path, "r", encoding="utf-8") as f: reader = csv.reader(f) # 跳过表头(如果CSV有表头) # next(reader) # 逐行添加数据 for row_idx, row_data in enumerate(reader): self.table.insertRow(row_idx) for col_idx, col_data in enumerate(row_data): item = QTableWidgetItem(col_data) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(row_idx, col_idx, item) QMessageBox.information(self, "成功", "CSV文件导入成功!") except Exception as e: QMessageBox.critical(self, "错误", f"导入失败:{str(e)}") def export_csv(self): """导出表格数据到CSV""" file_path, _ = QFileDialog.getSaveFileName( self, "导出CSV文件", "", "CSV Files (*.csv)" ) if not file_path: return # 补充.csv后缀 if not file_path.endswith(".csv"): file_path += ".csv" try: # 写入CSV文件 with open(file_path, "w", encoding="utf-8", newline="") as f: writer = csv.writer(f) # 写入表头 headers = [self.table.horizontalHeaderItem(col).text() for col in range(self.table.columnCount())] writer.writerow(headers) # 写入数据 for row in range(self.table.rowCount()): row_data = [] for col in range(self.table.columnCount()): item = self.table.item(row, col) row_data.append(item.text() if item else "") writer.writerow(row_data) QMessageBox.information(self, "成功", "CSV文件导出成功!") except Exception as e: QMessageBox.critical(self, "错误", f"导出失败:{str(e)}") # ---------- 数据排序 ---------- def sort_data(self): """按选择的规则排序""" sort_type = self.sort_combo.currentText() if sort_type == "按ID升序": # 按第0列(ID)升序排序 self.table.sortItems(0, Qt.AscendingOrder) elif sort_type == "按年龄升序": # 按第3列(年龄)升序排序 self.table.sortItems(3, Qt.AscendingOrder) elif sort_type == "按年龄降序": # 按第3列(年龄)降序排序 self.table.sortItems(3, Qt.DescendingOrder) if __name__ == "__main__": app = QApplication(sys.argv) manager = TableManager() manager.show() sys.exit(app.exec_())四、综合案例:文本+表格的信息管理窗口 整合QTextEdit和QTableWidget,实现一个“用户信息管理窗口”——表格展示用户列表,选中用户后在文本区显示详情,支持编辑详情并保存: import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QHBoxLayout, QPushButton, QTextEdit, QMessageBox, QSplitter ) from PyQt5.QtCore import Qt, QSize class InfoManager(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("用户信息管理窗口(文本+表格综合)") self.resize(800, 500) # 1. 创建分割器(左右布局,可拖动调整宽度) splitter = QSplitter(Qt.Horizontal) # 2. 左侧表格区 self.table = QTableWidget() self.table.setColumnCount(3) self.table.setHorizontalHeaderLabels(["ID", "姓名", "性别"]) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) # 填充测试数据 test_data = [[1, "张三", "男"], [2, "李四", "女"], [3, "王五", "男"]] for row in range(len(test_data)): self.table.insertRow(row) for col in range(len(test_data[row])): item = QTableWidgetItem(str(test_data[row][col])) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(row, col, item) # 3. 右侧文本区(详情编辑) right_widget = QWidget() right_layout = QVBoxLayout(right_widget) # 文本编辑区 self.info_edit = QTextEdit() self.info_edit.setPlaceholderText("选中表格中的用户,查看/编辑详情...") self.info_edit.setFont(QtGui.QFont("微软雅黑", 11)) # 保存按钮 save_btn = QPushButton("保存详情") save_btn.setFixedSize(100, 30) # 添加到右侧布局 right_layout.addWidget(self.info_edit) right_layout.addWidget(save_btn, alignment=Qt.AlignCenter) # 4. 将表格和右侧控件添加到分割器 splitter.addWidget(self.table) splitter.addWidget(right_widget) # 设置分割器初始宽度比例 splitter.setSizes([300, 500]) # 5. 主布局 main_layout = QVBoxLayout() main_layout.addWidget(splitter) self.setLayout(main_layout) # 6. 绑定信号 self.table.clicked.connect(self.show_user_info) save_btn.clicked.connect(self.save_user_info) def show_user_info(self): """选中表格行,显示用户详情""" selected_items = self.table.selectedItems() if not selected_items: return row = selected_items[0].row() # 获取用户基础信息 user_id = self.table.item(row, 0).text() name = self.table.item(row, 1).text() gender = self.table.item(row, 2).text() # 构造详情文本 info = f"""用户详情(ID:{user_id}) 姓名:{name} 性别:{gender} 年龄:暂未填写 电话:暂未填写 邮箱:暂未填写 备注:无 """ self.info_edit.setPlainText(info) def save_user_info(self): """保存编辑后的详情""" if not self.info_edit.toPlainText(): QMessageBox.warning(self, "提示", "详情不能为空!") return QMessageBox.information(self, "成功", "用户详情保存成功!") # 实际项目中可将详情写入数据库/文件 if __name__ == "__main__": app = QApplication(sys.argv) manager = InfoManager() manager.show() sys.exit(app.exec_())五、常见问题排查 1. QTextEdit相关问题 问题1:富文本格式设置不生效 → 解决:确保先选中文本再点击格式按钮;检查mergeCurrentCharFormat是否正确传入格式对象; 问题2:保存的HTML文件打开乱码 → 解决:保存时指定encoding="utf-8"; 问题3:文本编辑区不自适应窗口缩放 → 解决:确保文本编辑区直接添加到垂直布局,未设置固定大小。 2. QTableWidget相关问题 问题1:表格数据显示不全 → 解决:用horizontalHeader().setStretchLastSection(True)让最后一列拉伸;或手动设置列宽setColumnWidth; 问题2:选中行获取不到数据 → 解决:selectedItems()返回的是选中的单元格列表,需通过item.row()获取行号,再遍历列获取整行数据; 问题3:CSV导入/导出乱码 → 解决:读写CSV时指定encoding="utf-8";Windows系统可尝试encoding="gbk"; 问题4:单元格无法编辑 → 解决:检查setEditTriggers是否设置为NoEditTriggers,如需编辑改为DoubleClicked或AllEditTriggers。 总结 QTextEdit:核心用于多行文本/富文本处理,支持纯文本和HTML格式,mergeCurrentCharFormat是设置富文本格式的核心方法; QTableWidget:核心用于结构化数据展示/编辑,重点掌握行列管理、单元格操作、数据导入导出; 两个控件常结合使用(如表格展示列表+文本区展示详情),是数据管理类应用的核心组合; 下一章我们将学习PyQt5的对话框控件(QDialog),包括标准对话框和自定义对话框,进一步完善界面的交互能力。 如果在实操中遇到文本/表格处理的问题,或者想拓展更复杂的功能(如表格单元格合并、富文本插入图片),欢迎在评论区留言讨论~ -
PHP开源影视短剧系统源码 - 全功能短剧平台解决方案(支持付费变现) PHP开源影视短剧系统源码:全功能短剧平台解决方案,开源可扩展 给大家分享一款专为短剧运营打造的开源资源——PHP开源影视短剧系统源码!基于ThinkPHP框架+MySQL数据库构建,整合视频播放、用户运营、营销推广、付费变现等全流程功能,无需复杂开发即可搭建高效易用的在线短剧平台,支持自由修改扩展,妥妥的短剧创业者、内容创作者及开发者的实用工具! mjxlsvwc.png图片 一、核心功能模块:覆盖短剧平台全场景需求 1. 视频播放与交互:打造沉浸式观看体验 支持多种视频格式在线播放,加载流畅不卡顿,搭配CDN加速进一步提升访问效率。 内置视频预览功能,用户观看前可快速了解剧情;支持抖音风格滑动切换剧集,搭配无限滑动技术,增强用户粘性。 配备弹幕评论功能,用户可实时互动,提升平台活跃度与观看趣味性。 2. 用户全生命周期管理:精准运营核心用户 完善的用户体系:支持用户注册、登录、个人信息管理,满足基础使用需求。 互动功能丰富:用户可收藏心仪短剧、发表评论,形成内容互动闭环,助力用户留存。 后台可管理用户评论与弹幕,筛选优质内容、清理违规信息,保障平台内容质量与秩序。 3. 内容运营:高效管理短剧资源 管理员通过后台可灵活添加、编辑、删除短剧内容,包括剧情介绍、剧情壁纸等配套素材。 支持短剧分类展示(如推荐、最新、热门、排行榜等),方便用户快速筛选心仪内容,提升查找效率。 提供丰富的内容展现形式,适配不同用户浏览习惯,增强平台吸引力。 4. 营销与变现:多渠道提升盈利效率 多元营销工具:支持推荐位、广告位配置,搭配会员优惠活动,快速吸引流量、转化用户。 双付费模式:同时支持会员订阅和单集单独购买,适配不同用户消费习惯与预算,拓宽盈利渠道。 成熟代理机制:助力平台快速扩大用户规模,提升市场覆盖范围与盈利能力。 5. 性能优化:保障高并发稳定运行 采用高效缓存机制与数据库优化技术,即使面临高并发访问,也能保持系统稳定流畅。 支持CDN加速适配,大幅提升视频加载速度,避免因卡顿影响用户体验。 二、核心特色:开源短剧平台的差异化优势 交互体验出色:无限流畅滑动+抖音式剧集切换,贴合当下用户使用习惯,降低操作门槛。 变现模式成熟:双付费模式+多元营销工具+代理机制,形成完整盈利闭环,助力快速变现。 开源可扩展:开放源代码,支持开发者自由修改、扩展功能,可根据业务需求定制化开发,适配不同场景。 技术架构稳定:基于ThinkPHP+MySQL成熟技术栈,代码结构清晰,部署与维护成本低。 三、适用场景:谁适合用这款源码? 短剧创业者:无需从零开发,快速搭建专属短剧平台,聚焦内容运营与变现,缩短项目上线周期。 内容创作者:搭建个人短剧发布与变现平台,通过会员或单集付费模式实现内容价值转化。 平台运营者:想要拓展短剧业务,借助系统的营销推广与用户运营工具,快速积累用户、提升盈利。 开发者:作为短剧平台开发参考案例,学习功能模块设计;或基于源码二次开发,定制专属功能与界面。 源码获取 PHP开源影视短剧系统源码 下载地址:https://pan.quark.cn/s/9979132528e2 提取码: -
腾讯换机助手 安卓iOS跨平台零流量数据迁移工具 换机必备 腾讯换机助手:跨平台数据迁移神器,零流量一键搞定换机难题 换手机最头疼的就是重要数据转移?腾讯官方出品的换机助手完美解决这个痛点!不管是安卓与iOS互传、同系统新机升级,还是手机与电脑数据互联,它都能实现安全、高速、零流量的数据迁移,不用手动录入信息、不用压缩文件画质,小白也能轻松操作,妥妥的换机必备工具! mjxlmvq5.png图片 一、核心功能:覆盖全场景数据迁移需求 1. 全品类数据无遗漏迁移 支持九大核心数据类型,从基础通讯信息到个性化内容全涵盖: 通讯类:联系人(含备注、分组)、短信(含验证码、聊天记录)、通话记录; 多媒体类:照片(保留相册分类、编辑记录)、视频(高清无损传输)、音乐(含歌词、播放列表); 应用与个性化类:手机应用(安卓支持迁移安装包,iOS支持同步应用列表)、浏览器书签、日程(含提醒设置); 特色类:微信资料(聊天记录、重要文件单独迁移,避免关键信息丢失)。 2. 跨平台无缝兼容,打破系统壁垒 彻底告别“系统不同不能传”的限制,全场景适配: 安卓↔iOS:跨系统迁移无压力,基础数据完美适配,不用担忧格式不兼容; 安卓↔安卓/ iOS↔iOS:同系统迁移更高效,应用配置、个性化设置同步转移,新机开机即还原旧机体验; 多设备互联:支持手机与Windows电脑、Mac(M1+芯片)、iPod touch间的数据互传,满足多设备数据管理需求。 3. 零流量高速传输,省时又省流 采用设备自建热点直连技术,传输体验拉满: 零流量消耗:无需WiFi、手机流量或数据线,外出没网也能轻松换机; 极速秒传:传输速度远超蓝牙,100张高清照片约1分钟完成,大体积4K视频也能快速传输; 无损品质:照片、视频不压缩画质,音乐不损失音质,应用数据不丢失配置。 4. 加密防护,隐私安全有保障 数据传输全程守护隐私,杜绝信息泄露: 双机直连不上云:数据仅在新旧设备间直接传输,不经过第三方服务器,避免云端存储风险; 加密传输技术:采用腾讯自研加密算法,数据传输过程中全程加密,防止被截取、偷窥; 授权验证机制:新机需扫码确认连接,仅授权设备可接收数据,避免陌生设备接入。 5. 3步极简操作,小白也能上手 界面设计简洁直观,步骤指引清晰,不用专业知识也能快速完成: 步骤1:新旧设备/手机与电脑均安装换机助手; 步骤2:旧设备发起“零流量转移”生成二维码,新设备/电脑扫码建立连接; 步骤3:勾选需要迁移的数据类型(支持全选或部分选择),点击“发送”即可等待完成。 二、核心特色:官方出品的差异化优势 1. 官方背书,兼容性与稳定性拉满 腾讯专业团队开发,适配市面上主流机型(华为、苹果、小米等),定期更新修复问题,不会因系统升级导致迁移失败,比第三方工具更靠谱。 2. 一机多用,不止于换机 除了换机场景,日常也能发挥大作用: 文件分享:朋友间互传高清照片、大视频,不用发微信压缩画质; 存储释放:手机存储满时,可将大文件迁移到电脑或另一台设备,快速释放空间; iOS额外福利:支持骚扰拦截功能,百万级号码库实时识别诈骗、推销来电,守护通话安全。 三、适用人群与场景 换新机用户:不管是跨系统切换(安卓换iOS或反之),还是同品牌升级,都能一键迁移所有数据,省去重新下载应用、录入联系人的麻烦; 多设备用户:拥有安卓手机+iPhone、手机+电脑的人群,可实现跨设备数据互联,不用依赖U盘或云盘; 注重隐私用户:担心云端传输泄露信息,选择双机直连加密传输,隐私更有保障; 小白/长辈用户:3步简单操作+中文清晰指引,不用求助他人,自己就能完成数据迁移。 四、使用小贴士 首次使用需授权WiFi、相册、通讯录、摄像头权限,否则无法正常建立连接和读取数据; 传输时保持新旧设备距离在1米内,避免热点信号弱导致传输中断; 传输完成后,建议核对联系人数量、照片完整性,确保无遗漏;若遇问题可通过“设置-我要反馈”联系官方客服。 APP下载 下载腾讯换机助手 下载地址:https://pan.quark.cn/s/f495ff74405f 提取码: 腾讯换机助手凭借跨平台兼容、全品类数据迁移、零流量高速传输、安全加密等优势,让换机过程变得轻松高效。不管你是准备换新机,还是需要跨设备传数据,这款官方工具都值得一试! -
太极工具箱v1.3.6下载 安卓无广告纯净版 百种实用工具聚合APP 太极工具箱v1.3.6:Android无广告纯净版聚合工具,百种功能轻松解决日常需求 给大家推荐一款超实用的Android端工具聚合APP——太极工具箱v1.3.6无广告纯净版!这款软件主打“轻量无扰+功能全面”,32.3MB的小巧体积不占手机内存,运行流畅不卡顿,不管是日常应急用工具、图片创意处理,还是查询设备信息,都能一站式满足,关键是全程无广告干扰,免费就能用所有功能,妥妥的手机必备“万能小助手”! mjxldmts.png图片 一、核心基础信息:快速了解这款工具 信息类别详情说明软件版本v1.3.6(无广告纯净版,无任何弹窗或推送广告,使用体验清爽)运行环境仅支持Android系统(适配主流Android版本,安装后无需复杂配置,打开即能用)软件大小32.3 MB(体积小巧,下载快、占用内存少,老旧手机也能流畅运行)界面语言全程中文界面,功能分类清晰,老人小孩也能轻松找到需要的工具二、四大核心功能模块:从日常到专业全覆盖 太极工具箱的功能按使用场景分为四大类,每类都包含多个高频实用工具,不用再下载多个单一工具APP,一个就能搞定所有需求: 1. 日常应急工具:生活小事不用愁 这类工具聚焦日常高频需求,关键时刻能帮上大忙: 基础便捷工具:手电筒(亮度可调,夜间找东西、走夜路超实用)、直尺(屏幕实时显示长度,临时量小物件尺寸)、量角器(DIY手工、学习画图时测角度)、LED字幕(输入文字生成滚动字幕,演唱会、接机举牌超吸睛)。 时间与天气工具:万年历(查节气、节假日、干支纪年,传统节日安排更省心)、天气查询(实时显示温度、降水概率,出门前快速了解天气)、日期计算器(计算两个日期之间的天数、工作日,规划行程或项目截止时间很方便)、时间屏保(设置个性化时间显示,手机闲置时也能当小闹钟)。 2. 专业传感器工具:手机秒变“测量仪” 利用手机硬件特性,将普通手机变成专业测量工具,适合学生、DIY爱好者或需要临时测量的场景: 环境与物理测量:指南针(户外迷路时定位方向,徒步、露营必备)、分贝仪(检测环境噪音,避免噪音干扰学习或休息)、金属探测器(找掉落的小金属零件、钥匙,或检测物体是否含金属)、水平仪(挂照片、装家具时找水平,避免歪歪扭扭)。 设备状态监测:重力传感器(直观显示手机倾斜角度,物理实验、游戏辅助都能用)、磁力传感器(检测磁场强度,科普或特殊场景测量)、方向传感器(精准显示方位,配合指南针使用更准确)、电池检测(查看电池剩余电量、健康状态,了解手机续航情况)。 3. 图片创意工具:轻松玩转图片处理 不管是日常修图、制作表情包,还是设计头像壁纸,这类工具都能满足创意需求,无需专业修图软件: 图片编辑与美化:壁纸大全(内置海量高清壁纸,涵盖风景、动漫、简约等风格,一键设置手机桌面)、头像大全(多种风格头像可选,不用再手动找图,直接保存使用)、图片水印(添加文字或图案水印,保护原创图片不被盗用)、图片取色(提取图片中的任意颜色代码,设计、画画时精准配色)。 图片创意玩法:GIF分解(将GIF动图拆分成单张图片,提取喜欢的帧制作表情包)、九空格切图(把一张图分成9张,朋友圈发九宫格拼图更整齐美观)、纯色图制作(生成任意颜色的纯色图片,当壁纸或设计背景很实用)、图片像素化(将图片处理成像素风格,打造复古或创意效果)。 4. 查询与辅助工具:快速获取关键信息 这类工具帮你快速查询实用信息,或了解手机状态,提升使用效率: 信息查询工具:二维码生成(支持带LOGO的个性化二维码,生成微信、网址、联系方式二维码,方便分享)、手机号归属地查询(输入手机号,快速了解号码所属运营商和地区,识别陌生号码)、IP查询地理位置(查IP对应的地区,了解网络状态或识别异地登录)、身份证查询(验证身份证号码格式是否正确,避免输入错误)。 手机辅助工具:屏幕检测(检测屏幕是否有坏点、漏光,新买手机或日常检测屏幕状态)、手机信息查看(一键显示手机型号、系统版本、硬件配置等信息,了解手机性能或维修时提供参考)。 三、三大核心特色:为什么值得下载? 1. 无广告纯净体验,使用不被打扰 作为“纯净版”,软件全程无任何弹窗广告、开屏广告或推送广告,打开工具、切换功能时不会被广告打断,专注处理需求,这点比很多同类工具APP更良心。 2. 功能聚合度高,告别“APP臃肿” 整合近百种功能,涵盖日常、专业、创意、查询四大场景,不用为了一个小功能下载一个APP,既节省手机存储空间,又减少桌面图标杂乱,找工具更高效。 3. 免费全功能开放,零门槛使用 所有工具均免费使用,不用开通会员、充值付费,也没有“试用功能”限制;界面操作简单,功能图标直观易懂,打开APP后点击对应工具就能用,新手不用学习就能上手。 四、适用场景:谁最需要这款工具? 学生党:直尺、量角器辅助学习,图片工具制作手抄报、PPT配图,日期计算器规划学习计划,一个APP解决多种学习需求。 上班族:二维码生成分享工作文件,图片水印保护工作图片,手机信息查询了解设备状态,提升办公效率。 户外爱好者:指南针、分贝仪、金属探测器,徒步、露营时应对各种突发情况,关键时刻能派上用场。 创意达人:GIF分解、九空格切图、头像壁纸制作,轻松玩转社交平台内容,打造个性化分享素材。 普通用户:手电筒、天气查询、日期计算等日常工具,解决生活中的小麻烦,不用再下载多个单一工具。 五、使用建议 首次打开APP时,建议先浏览“我的工具箱”页面,熟悉功能分类,后续找工具更快速; 常用工具可以添加到“我的工具箱”收藏,下次打开直接点击,不用再翻找分类; 使用传感器类工具时,尽量保持手机平稳,避免手抖影响测量精度; 图片处理后的文件会自动保存到手机相册,可直接在相册中查看或分享。 APP下载 太极工具箱 1.3.6.zip 下载地址:https://pan.quark.cn/s/e1f3b5ab2316 提取码: 总之,太极工具箱v1.3.6无广告纯净版是一款“小而全”的实用工具APP,体积小、功能全、无广告、免费使用,不管是日常应急、学习办公,还是创意处理,都能满足需求,Android用户值得一试! -
YPay源支付云端一键部署代码 对应CentOS/Ubuntu/Debian系统 请勿购买,目前源已失效,等待我镜像一份 YPay源支付云端部署:3套专属代码对应不同系统,零失误实操 YPay源支付云端的一键部署脚本,针对CentOS、Ubuntu、Debian这三类常用Linux系统做了适配优化,3套代码对应不同环境,能避免“系统不兼容导致部署失败”的问题。下面分系统讲清每套代码的用法: mjx1ckkw.png图片 一、先明确3套代码的适用场景 代码序号适配系统核心特点代码1CentOS 7/8/9适配RPM包管理,部署速度快代码2Ubuntu 18.04+/20.04+适配DEB包管理,兼容性强代码3Debian 10+/11+轻量系统专属,资源占用低二、分系统实操:3套代码的部署步骤 场景1:CentOS系统(用代码1) 操作步骤: 以root用户登录服务器终端,执行专属部署代码: 隐藏内容,请前往内页查看详情 若提示“wget未安装”,先补装依赖: 隐藏内容,请前往内页查看详情 后续选择部署选项、等待完成的流程,和之前教程一致(新手选“01. 一键自动安装云端”)。 场景2:Ubuntu系统(用代码2) 操作步骤: 以root用户登录服务器终端,执行专属部署代码: 隐藏内容,请前往内页查看详情 若提示“wget未安装”,先补装依赖: 隐藏内容,请前往内页查看详情 同样选择对应部署选项,等待脚本自动完成环境配置、服务启动。 场景3:Debian系统(用代码3) 操作步骤: 以root用户登录服务器终端,执行专属部署代码: 隐藏内容,请前往内页查看详情 若提示“wget未安装”,先补装依赖: 隐藏内容,请前往内页查看详情 选择部署选项后,脚本会适配Debian的轻量特性,优先占用少的资源完成部署。 三、3套代码的通用注意事项 权限必须是root:非root用户会提示“无法创建目录/启动服务”,需切换root或加sudo前缀。 网络要稳定:若下载脚本卡住,可换国内镜像源(比如CentOS换阿里云源)后重试。 端口统一检查:不管用哪套代码,部署完成后都要通过“09. 一键查看防火墙状态”确认端口开放(默认常用端口是8080、8888)。 四、评论区补充的跨系统避坑点 CentOS用户:若提示“yum仓库不可用”,先执行yum clean all && yum makecache更新仓库。 Ubuntu/Debian用户:若提示“apt锁占用”,执行rm /var/lib/dpkg/lock-frontend解锁后重试。 这样根据自己的服务器系统选对应的代码,就能彻底避免“代码不匹配导致部署失败”的问题,零基础也能精准完成YPay源支付云端的搭建~ -
秒解再续前缘主题百度统计 “没有当前站点”:域名适配优化教程 秒解joe再续前缘百度统计“没有当前站点”:域名适配优化指南 很多使用joe再续前缘的站长,在百度统计配置中都会踩一个坑——明明API密钥、站点信息都填对了,前端却始终显示“没有当前站点”,导致统计数据无法正常加载。其实这不是配置问题,而是主题默认的域名匹配逻辑过于严格,今天就用一篇结构化教程,带大家一步到位解决问题! mjw77r4q.png图片 一、问题直击:你是否遇到这些现象? 主题后台已完整填写百度统计API的access_token、refresh_token、client_id等信息; 百度统计后台已添加当前站点,且状态正常; 前端页面统计区域显示“没有当前站点”,无任何统计数据展示; 排查后发现,百度统计API能正常返回站点列表,但主题无法匹配到当前域名。 二、问题根源:域名匹配逻辑的“严格性”陷阱 joe再续前缘中🐔🐔航写的默认的百度统计代码中,域名匹配采用“完全字符一致”规则,但实际场景中很容易出现格式差异: 百度统计API返回域名:www.xxx.com,主题JOE_DOMAIN常量:xxx.com; 百度统计API返回域名:http://xxx.com,主题JOE_DOMAIN常量:https://xxx.com; 域名大小写差异(如XXX.com与xxx.com)、端口号冗余等。 这些细微格式差异,会让主题代码判定“无匹配站点”,最终返回错误提示。核心需求是:让域名匹配具备“容错性”,忽略无关格式差异。 三、解决方案:3步替换优化代码 3.1 准备工作:明确文件路径 操作前先确认文件位置,避免找错文件: 服务器环境:宝塔面板(可视化操作更高效); 核心路径:网站根目录 → usr/themes/joe/(若主题文件夹重命名,对应修改); 目标文件:通常为 core/function.php 或 api.php(含“没有当前站点”文本的文件)。 3.2 第一步:定位目标代码块 登录宝塔面板,进入网站根目录,导航至 usr/themes/joe/; 点击文件管理器右上角“搜索”,输入关键词“没有当前站点”; 搜索结果中打开对应文件,找到 public static function baiduStatistic($self) 方法——该方法即为百度统计核心逻辑,从方法定义到结束大括号 } 为完整代码块。 3.3 第二步:替换为优化后代码 将以下优化后的代码,完整替换原 baiduStatistic 方法(删除原有代码,粘贴新代码): // 百度统计展示 public static function baiduStatistic($self) { $normalizeDomain = function ($domain) { $domain = preg_replace('/^https?:\/\//', '', $domain); $domain = preg_replace('/^www\./', '', $domain); return strtolower(trim($domain)); }; $statistics_config = \joe\baidu_statistic_config(); if (!is_array($statistics_config)) { return (array('access_token' => 'off')); } if (empty($statistics_config['access_token'])) { return (array('access_token' => 'off')); } $baidu_list = function () use ($statistics_config, $self) { $url = 'https://openapi.baidu.com/rest/2.0/tongji/config/getSiteList?access_token=' . $statistics_config['access_token']; $data = json_decode(file_get_contents($url), true); if (isset($data['error_code'])) { if ($data['error_code'] == 111) { $refresh_token = \network\http\get('http://openapi.baidu.com/oauth/2.0/token', [ 'grant_type' => 'refresh_token', 'refresh_token' => $statistics_config['refresh_token'], 'client_id' => $statistics_config['client_id'], 'client_secret' => $statistics_config['client_secret'] ])->toArray(); if (is_array($refresh_token)) { $theme_options = self::$options->__get('theme:' . THEME_NAME); if (empty($theme_options)) return (['message' => '请更新您的 access_token']); $backup_field = 'theme:' . THEME_NAME . '_backup'; $backup = Db::name('options')->where('name', $backup_field)->find(); if ($backup) { Db::name('options')->where('name', $backup_field)->update(['value' => $theme_options]); } else { Db::name('options')->where('name', $backup_field)->insert(['user' => '0', 'name' => $backup_field, 'value' => $theme_options]); } $theme_options = unserialize($theme_options); $theme_options['baidu_statistics'] = trim($refresh_token['access_token']) . "\r\n" . trim($refresh_token['refresh_token']) . "\r\n" . $statistics_config['client_id'] . "\r\n" . $statistics_config['client_secret']; $options_update = Db::name('options')->where('name', 'theme:' . THEME_NAME)->update(['value' => serialize($theme_options)]); if ($options_update) { $statistics_config['access_token'] = $refresh_token['access_token']; $new_url = 'https://openapi.baidu.com/rest/2.0/tongji/config/getSiteList?access_token=' . $statistics_config['access_token']; $new_data = json_decode(file_get_contents($new_url), true); return $new_data['list'] ?? []; } else { return ['message' => 'access_token 更新失败!']; } } else { return ['message' => '请更新您的 access_token']; } } return $data; } return $data['list']; }; $web_metrics = function ($site_id, $start_date, $end_date) use ($statistics_config) { $access_token = $statistics_config['access_token']; $url = "https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=$access_token&site_id=$site_id&method=trend/time/a&start_date=$start_date&end_date=$end_date&metrics=avg_visit_time,ip_count,pv_count,&gran=day"; $data = \network\http\post($url)->toArray(); if (is_array($data)) { $data = $data['result']['sum'][0]; } else { $data = 0; } return $data; }; $list = $baidu_list(); if (!is_array($list)) { return $list; } for ($i = 0; $i < count($list); $i++) { if ($normalizeDomain($list[$i]['domain']) === $normalizeDomain(JOE_DOMAIN)) { $list = $list[$i]; break; } } if (is_array($list) && isset($list['domain'])) { $today = $web_metrics($list['site_id'], date('Ymd'), date('Ymd')); $yesterday = $web_metrics($list['site_id'], date('Ymd', strtotime("-1 days")), date('Ymd', strtotime("-1 days"))); $moon = $web_metrics($list['site_id'], date('Ym') . '01', date('Ymd')); $data = [ 'code' => 200, 'today' => $today, 'yesterday' => $yesterday, 'month' => $moon ]; return ($data); } else { return ['message' => '没有当前站点']; } }3.4 第三步:保存生效 点击文件编辑器右上角“保存”,清空浏览器缓存(Ctrl+Shift+Del),重新访问网站前端——“没有当前站点”提示消失,统计数据正常加载! mjw78h99.png图片 四、核心修改解析:域名标准化适配 优化代码的核心是新增“域名标准化”逻辑,让不同格式的域名统一规则后再匹配,关键代码如下: $normalizeDomain = function ($domain) { $domain = preg_replace('/^https?:\/\//', '', $domain); // 去除http/https协议头 $domain = preg_replace('/^www\./', '', $domain); // 去除www前缀 return strtolower(trim($domain)); // 转为小写+去除空格 }; 原逻辑:$list[$i]['domain'] == JOE_DOMAIN(完全字符匹配); 新逻辑:$normalizeDomain($list[$i]['domain']) === $normalizeDomain(JOE_DOMAIN)(标准化后匹配)。 示例:无论原域名是www.xxx.com“https://XXX.com”还是xxx.com:80,都会被标准化为xxx.com,确保匹配成功。 此外,代码还优化了access_token刷新后的逻辑——刷新成功后自动用新token重新获取站点列表,无需手动刷新页面,流程更顺畅。 五、常见问题排查 5.1 替换后仍显示“没有当前站点” 检查JOE_DOMAIN常量是否定义:需确保主题配置中已正确设置该常量,且不为空; 核实百度统计站点:登录百度统计后台,确认当前站点已添加,且域名与标准化后的JOE_DOMAIN一致; 检查文件路径:确认修改的是“含‘没有当前站点’文本”的目标文件,而非其他同名文件。 5.2 替换后出现语法错误 确保代码完整复制:未遗漏大括号、分号等语法符号; 检查PHP版本:确保服务器PHP版本≥8.0(joe再续前缘最低要求),避免语法兼容问题。 5.3 access_token频繁失效 核实refresh_token有效性:百度统计refresh_token有效期较长,若失效需重新申请API密钥; 检查client_id/client_secret:确保与百度统计开放平台配置一致,无拼写错误。 六、总结 joe再续前缘百度统计“没有当前站点”的问题,本质是域名格式匹配的“容错性不足”。通过新增域名标准化逻辑,能快速解决不同格式域名的匹配问题,且不影响原有统计功能和API交互流程。 整个操作仅需3步:定位文件→替换代码→保存生效,无需复杂配置,新手也能轻松完成。如果在操作中遇到其他问题,欢迎在评论区留言讨论~ -
PyQt5布局管理器进阶:网格布局与表单布局(附实战代码) 第6篇:PyQt5布局管理器进阶:网格布局与表单布局(完整代码) mjw558rv.png图片 哈喽~ 欢迎来到PyQt5系列的第6篇!上一章我们通过“简易文本编辑器”实战,巩固了线性布局(QVBoxLayout/QHBoxLayout)的用法。但在实际开发中,很多复杂界面(比如计算器、用户信息表单、数据展示表格)无法只用线性布局满足——要么控件排列混乱,要么自适应效果差。今天我们就来学习两种进阶布局管理器:网格布局(QGridLayout)和表单布局(QFormLayout),彻底解决复杂界面的排版难题! 一、先明确:进阶布局的核心作用 在学习具体布局前,先搞清楚两种布局的适用场景,避免用错地方: 网格布局(QGridLayout):控件按“行×列”的网格排列,适合需要精准控制控件位置的场景(如计算器按钮、表格数据展示);支持控件跨多行/多列,灵活性极高; 表单布局(QFormLayout):专门用于“标签+输入框”的表单场景(如用户注册/登录表单、信息填写窗口),自动对齐标签和输入框,界面规整且开发高效。 核心优势:两种布局都支持自适应——窗口缩放时,控件会按预设规则自动调整大小和位置,无需手动计算坐标。 二、网格布局(QGridLayout)详解:从基础到实战 网格布局的核心逻辑是“划分网格、给控件分配行和列”,比如将界面划分为3行3列,每个控件占1个“格子”,也可以让控件占2行1列(跨行吗)、1行2列(跨列)。 1. 网格布局基础用法(完整代码) 先实现一个简单的3×3网格,放置9个按钮,演示基础的行、列分配: import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QPushButton, QGridLayout, QLabel ) from PyQt5.QtCore import Qt class GridLayoutDemo(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("QGridLayout网格布局基础演示") self.resize(400, 300) # 1. 创建网格布局实例 grid_layout = QGridLayout() # 设置控件间距(格子之间的距离) grid_layout.setSpacing(10) # 设置边距(布局与窗口边缘的距离) grid_layout.setContentsMargins(20, 20, 20, 20) # 2. 创建控件并添加到网格布局 # 核心方法:addWidget(控件, 行号, 列号, 占用行数, 占用列数) # 行号、列号从0开始;占用行数/列数默认是1(可不写) for i in range(3): # 行:0、1、2 for j in range(3): # 列:0、1、2 btn = QPushButton(f"按钮({i},{j})") # 添加到网格的(i,j)位置,占1行1列 grid_layout.addWidget(btn, i, j) # 3. 额外添加一个跨列控件(占1行2列) cross_col_btn = QPushButton("跨2列按钮") grid_layout.addWidget(cross_col_btn, 3, 0, 1, 2) # 第4行(索引3),第0列,占1行2列 # 4. 额外添加一个跨行控件(占2行1列) cross_row_btn = QPushButton("跨2行按钮") grid_layout.addWidget(cross_row_btn, 0, 3, 2, 1) # 第0行,第4列(索引3),占2行1列 # 5. 将布局绑定到窗口 self.setLayout(grid_layout) if __name__ == "__main__": app = QApplication(sys.argv) window = GridLayoutDemo() window.show() sys.exit(app.exec_())mjw55cag.png图片 2. 网格布局关键方法解析 网格布局的核心是addWidget()方法,参数含义必须记牢: addWidget(控件, row, column, rowSpan, columnSpan) # row:控件所在的行号(从0开始) # column:控件所在的列号(从0开始) # rowSpan:控件占用的行数(默认1,即不跨行) # columnSpan:控件占用的列数(默认1,即不跨列)其他常用方法: setSpacing(像素值):设置相邻控件之间的间距,避免控件挤在一起; setContentsMargins(左, 上, 右, 下):设置布局与窗口边缘的距离,提升界面美观度; setRowStretch(行号, 拉伸系数):设置某一行的拉伸权重(窗口缩放时,拉伸系数大的行占更多空间); setColumnStretch(列号, 拉伸系数):设置某一列的拉伸权重,同理。 3. 网格布局实战:简易计算器界面(核心场景) 计算器是网格布局的典型应用——按钮按固定网格排列,部分按钮(如“0”“=”)跨列。我们实现一个简易计算器的界面(含输入框+按钮区): import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QPushButton, QGridLayout, QLineEdit ) from PyQt5.QtCore import Qt class SimpleCalculator(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("简易计算器(网格布局实战)") self.resize(350, 400) # 1. 创建主布局(垂直布局:输入框在上,按钮区在下) main_layout = QGridLayout() main_layout.setSpacing(10) main_layout.setContentsMargins(15, 15, 15, 15) # 2. 创建输入框(占1行4列) self.input_edit = QLineEdit() self.input_edit.setAlignment(Qt.AlignRight) # 文本右对齐(符合计算器习惯) self.input_edit.setStyleSheet("font-size: 20px; padding: 10px;") self.input_edit.setReadOnly(True) # 输入框只读,通过按钮输入 main_layout.addWidget(self.input_edit, 0, 0, 1, 4) # 第0行,第0列,占1行4列 # 3. 定义计算器按钮文本(按网格顺序排列) btn_texts = [ '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '=', '+', 'C' # 清空按钮 ] # 4. 给按钮分配行和列,添加到网格布局 row = 1 # 从第1行开始(第0行是输入框) col = 0 for text in btn_texts: btn = QPushButton(text) btn.setStyleSheet("font-size: 16px; padding: 15px;") # 特殊处理:0按钮跨2列,C按钮跨2列 if text == '0': main_layout.addWidget(btn, row, col, 1, 2) # 占1行2列 col += 2 # 列号+2(跳过一个格子) elif text == 'C': main_layout.addWidget(btn, row, col, 1, 2) # 占1行2列 col += 2 else: main_layout.addWidget(btn, row, col) # 默认占1行1列 col += 1 # 每4列换行(计算器是4列按钮) if col >= 4: col = 0 row += 1 # 5. 绑定布局到窗口 self.setLayout(main_layout) # 6. 绑定按钮点击信号(简单演示:点击按钮显示文本到输入框) for i in range(main_layout.count()): widget = main_layout.itemAt(i).widget() if isinstance(widget, QPushButton): widget.clicked.connect(self.on_btn_click) def on_btn_click(self): """按钮点击槽函数:将按钮文本显示到输入框""" sender = self.sender() text = sender.text() if text == 'C': # 清空输入框 self.input_edit.clear() elif text == '=': # 简单计算(实际项目需处理异常,此处简化) try: result = eval(self.input_edit.text()) self.input_edit.setText(str(result)) except: self.input_edit.setText("错误") else: # 拼接文本 current_text = self.input_edit.text() self.input_edit.setText(current_text + text) if __name__ == "__main__": app = QApplication(sys.argv) calculator = SimpleCalculator() calculator.show() sys.exit(app.exec_())4. 计算器界面亮点 用网格布局精准还原计算器的按钮排列,“0”和“C”按钮跨列,符合实际计算器的交互习惯; 结合垂直布局的思路,将输入框和按钮区整合,界面层次清晰; 实现了基础的计算逻辑(数字拼接、清空、结果计算),信号与槽绑定简洁高效。 三、表单布局(QFormLayout)详解:高效实现表单界面 表单布局是“标签+输入框”的专用布局,无需手动调整对齐方式——它会自动将标签放在左侧、输入控件放在右侧,且所有标签和输入框分别对齐,开发效率极高。 1. 表单布局基础用法(完整代码) 实现一个简单的用户注册表单,包含“用户名、密码、邮箱、电话”四个字段: import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QLabel, QLineEdit, QPushButton, QFormLayout, QVBoxLayout, QComboBox ) from PyQt5.QtCore import Qt class FormLayoutDemo(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("QFormLayout表单布局基础演示") self.resize(400, 300) # 1. 创建主布局(垂直布局:表单在上,按钮在下) main_layout = QVBoxLayout() main_layout.setSpacing(20) main_layout.setContentsMargins(30, 30, 30, 30) # 2. 创建表单布局实例 form_layout = QFormLayout() form_layout.setSpacing(15) # 标签与输入框、行与行之间的间距 # 3. 创建标签和输入控件,添加到表单布局 # 核心方法:addRow(标签文本/标签控件, 输入控件) # 方式1:直接传标签文本(自动生成QLabel) form_layout.addRow("用户名:", QLineEdit()) # 方式2:传QLabel控件(可自定义标签样式) pwd_label = QLabel("密码:") pwd_label.setStyleSheet("color: #e74c3c;") pwd_edit = QLineEdit() pwd_edit.setEchoMode(QLineEdit.Password) # 密码隐藏 form_layout.addRow(pwd_label, pwd_edit) # 方式3:输入控件可以是其他类型(如下拉框) form_layout.addRow("性别:", QComboBox()) # 方式4:添加提示标签(跨两列) tip_label = QLabel("* 带星号的为必填项") tip_label.setStyleSheet("color: #95a5a6; font-size: 12px;") form_layout.addRow(tip_label) # 无输入控件时,标签跨两列 # 4. 调整标签对齐方式(默认左对齐,可改为右对齐) form_layout.setLabelAlignment(Qt.AlignRight) # 5. 创建提交按钮 submit_btn = QPushButton("提交表单") submit_btn.setStyleSheet("background-color: #3498db; color: white; padding: 8px;") # 6. 将表单布局和按钮添加到主布局 main_layout.addLayout(form_layout) main_layout.addWidget(submit_btn, alignment=Qt.AlignCenter) # 7. 绑定布局到窗口 self.setLayout(main_layout) if __name__ == "__main__": app = QApplication(sys.argv) window = FormLayoutDemo() window.show() sys.exit(app.exec_())2. 表单布局关键方法解析 addRow(标签, 输入控件):核心方法,添加一行表单;标签可以是字符串(自动生成QLabel)或QLabel实例,输入控件可以是QLineEdit、QComboBox等任意交互控件; setLabelAlignment(对齐方式):设置标签的对齐方式(如Qt.AlignRight让标签右对齐,与输入框间距更紧凑); setSpacing(像素值):设置“标签与输入框之间”和“相邻行之间”的间距; setFieldGrowthPolicy(策略):设置输入控件的拉伸策略(如QFormLayout.ExpandingFieldsGrow让输入控件随窗口缩放而拉伸)。 3. 表单布局实战:完整用户信息登记表单 整合表单布局和之前学的控件,实现一个完整的用户信息登记表单,包含输入框、下拉框、复选框,添加表单验证逻辑: import sys from PyQt5.QtWidgets import ( QApplication, QWidget, QLabel, QLineEdit, QPushButton, QFormLayout, QVBoxLayout, QComboBox, QCheckBox, QMessageBox ) from PyQt5.QtCore import Qt class UserInfoForm(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.setWindowTitle("用户信息登记表单(表单布局实战)") self.resize(450, 350) self.setStyleSheet("font-size: 14px; color: #2c3e50;") # 1. 主布局 main_layout = QVBoxLayout() main_layout.setSpacing(20) main_layout.setContentsMargins(30, 30, 30, 30) # 2. 表单布局 form_layout = QFormLayout() form_layout.setSpacing(15) form_layout.setLabelAlignment(Qt.AlignRight) # 设置输入控件拉伸(随窗口缩放) form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) # 3. 表单控件初始化 self.user_edit = QLineEdit() self.user_edit.setPlaceholderText("请输入用户名(3-10个字符)") self.pwd_edit = QLineEdit() self.pwd_edit.setEchoMode(QLineEdit.Password) self.pwd_edit.setPlaceholderText("请输入密码(6-16个字符)") self.email_edit = QLineEdit() self.email_edit.setPlaceholderText("请输入邮箱(如xxx@xxx.com)") self.gender_combo = QComboBox() self.gender_combo.addItems(["男", "女", "保密"]) self.phone_edit = QLineEdit() self.phone_edit.setPlaceholderText("请输入手机号(11位数字)") # 4. 添加表单行 form_layout.addRow("用户名*:", self.user_edit) form_layout.addRow("密码*:", self.pwd_edit) form_layout.addRow("邮箱*:", self.email_edit) form_layout.addRow("性别:", self.gender_combo) form_layout.addRow("手机号:", self.phone_edit) # 同意条款复选框(跨两列) self.agree_check = QCheckBox("我已阅读并同意《用户服务条款》") form_layout.addRow(self.agree_check) # 5. 提交按钮 self.submit_btn = QPushButton("提交信息") self.submit_btn.setStyleSheet(""" QPushButton { background-color: #27ae60; color: white; padding: 10px; border: none; border-radius: 4px; } QPushButton:hover { background-color: #219653; } """) # 6. 结果显示标签 self.result_label = QLabel("") self.result_label.setAlignment(Qt.AlignCenter) # 7. 添加到主布局 main_layout.addLayout(form_layout) main_layout.addWidget(self.submit_btn, alignment=Qt.AlignCenter) main_layout.addWidget(self.result_label) # 8. 绑定布局和信号 self.setLayout(main_layout) self.submit_btn.clicked.connect(self.check_form) def check_form(self): """表单验证逻辑:检查必填项、格式正确性""" # 1. 获取表单内容 username = self.user_edit.text().strip() password = self.pwd_edit.text().strip() email = self.email_edit.text().strip() gender = self.gender_combo.currentText() phone = self.phone_edit.text().strip() # 2. 验证必填项 if not username: QMessageBox.warning(self, "验证失败", "用户名不能为空!") return if not password: QMessageBox.warning(self, "验证失败", "密码不能为空!") return if not email: QMessageBox.warning(self, "验证失败", "邮箱不能为空!") return if not self.agree_check.isChecked(): QMessageBox.warning(self, "验证失败", "请同意用户服务条款!") return # 3. 验证格式(简化版) if len(username) < 3 or len(username) > 10: QMessageBox.warning(self, "验证失败", "用户名长度需在3-10个字符之间!") return if len(password) < 6 or len(password) > 16: QMessageBox.warning(self, "验证失败", "密码长度需在6-16个字符之间!") return if "@" not in email: QMessageBox.warning(self, "验证失败", "邮箱格式不正确(需包含@)!") return if phone and len(phone) != 11: QMessageBox.warning(self, "验证失败", "手机号需为11位数字!") return # 4. 验证通过,显示结果 result = f""" 信息提交成功! 用户名:{username} 性别:{gender} 邮箱:{email} 手机号:{phone if phone else "未填写"} """ self.result_label.setText(result) self.result_label.setStyleSheet("color: #27ae60;") if __name__ == "__main__": app = QApplication(sys.argv) form = UserInfoForm() form.show() sys.exit(app.exec_())5. 实战表单亮点 用表单布局快速实现规整的表单界面,标签右对齐,输入框自适应拉伸,开发效率高; 添加了完整的表单验证逻辑(必填项检查、格式验证),用QMessageBox弹出提示,提升用户体验; 结合了多种控件(输入框、下拉框、复选框),覆盖实际表单的常见场景; 美化了按钮样式(悬停效果、圆角),界面更美观。 四、布局嵌套技巧:复杂界面的核心思路 实际开发中,很少用单一布局完成复杂界面,而是通过“布局嵌套”组合使用——比如“主布局(垂直)”包含“表单布局”和“网格布局”,再搭配“水平布局”排列按钮。 嵌套核心原则: 先划分界面大区域(如“顶部标题区、中间内容区、底部按钮区”),用主布局(垂直/水平)管理; 每个小区域内部,根据控件类型选择合适的子布局(网格/表单/线性); 用addLayout()方法将子布局添加到主布局,实现层次化管理。 五、常见问题排查 问题1:网格布局控件重叠/位置错乱 → 解决:检查行号、列号是否正确,避免多个控件分配到同一个格子;跨行列时注意rowSpan和columnSpan的数值; 问题2:表单布局标签和输入框不对齐 → 解决:用setLabelAlignment()统一标签对齐方式;避免手动设置输入控件的固定宽度(让布局自动适配); 问题3:窗口缩放时控件不拉伸 → 解决:给布局添加拉伸系数(setRowStretch/setColumnStretch),或设置输入控件的拉伸策略(如表单布局的setFieldGrowthPolicy); 问题4:布局嵌套后界面混乱 → 解决:先画界面草图,明确大区域和子区域的划分;给每个布局添加setSpacing和setContentsMargins,避免间距混乱。 总结 本章我们掌握了两种进阶布局管理器的核心用法: 网格布局(QGridLayout):适合“行×列”的规整排列场景(如计算器),支持控件跨行列,灵活性极高; 表单布局(QFormLayout):专门用于“标签+输入框”的表单场景,自动对齐,开发效率高; 布局嵌套是复杂界面的核心思路,先划分大区域,再用子布局管理小区域。 下一章我们将学习PyQt5的文本与表格控件(QTextEdit与QTableWidget),进一步拓展界面的功能边界。如果在布局实操中遇到问题,或者有复杂界面的排版需求,欢迎在评论区留言讨论~ -
免费分享石大导航网站HTML源码 - 学生专属简洁校园导航工具 石大导航网站HTML源码:免费学生专属简洁导航资源分享 给大家免费分享一款专为学生群体打造的实用导航资源——HTML简洁大气石大导航网站源码!无需付费,石大学子、学生群体及需要简洁导航的用户都能免费获取,界面清爽简约,贴合日常上网与学习需求,不管是快速访问校园官网、学习平台,还是常用工具网站,都能高效直达,妥妥的轻量化便捷导航工具! mjw50t1c.png图片 一、核心资源信息 核心定位(资源核心价值):专为石大学子定制开发,聚焦校园学习与日常上网场景,整合校园官网、学习平台、工具网站、娱乐平台等各类常用网址,分类清晰直观,解决网址查找繁琐的问题,提升上网与学习效率;同时兼顾通用需求,普通用户也可按需修改使用。 技术与部署(资源实用性):基于HTML+JavaScript开发,属于纯静态源码,无需数据库支持,部署门槛极低,上传服务器即可使用,适配各类主机空间;界面简洁无冗余,加载速度快,无需复杂配置,学生或初学者都能轻松上手操作。 注意事项(资源使用提醒):源码集成的天气插件已无法使用,需在HTML代码底部更换为其他天气插件,避免影响网站打开速度与使用体验。 二、核心功能与特色(免费解锁清爽导航体验) 精准网址分类:预设贴合学生需求的网址分类,包括常用(石河子大学官网、各学院官网、教务处官网、一站式服务平台等校园核心网址)、学习(智慧树、雨课堂、U校园、优慕课、itest等学习平台)、工具与娱乐(QQ音乐、网易云音乐、抖音、哔哩哔哩等),无需手动收藏,快速定位目标网站。 实用附加功能:页面内置日历显示,方便查看日期;支持关键词搜索功能,若未输入关键词,将自动跳转到自定义网址,满足个性化使用需求。 界面与体验优势:整体设计简洁大气、清爽简约,无冗余信息干扰,视觉体验舒适;操作逻辑简单,无需学习成本,学生群体可直接上手使用,提升上网浏览心情。 三、资源适用场景(免费资源适配多需求) 这款免费分享的源码用途明确,适配场景集中: 石大学子:作为日常上网与学习的专属导航,快速访问校园官网、学习平台,省去记忆或查找网址的麻烦,提升学习与办事效率。 其他学生群体:可根据自身学校的常用网址,修改替换预设链接,打造专属校园导航网站,适配不同高校学生的需求。 个人用户:喜欢简洁导航风格的用户,可用于整理个人常用网址,打造干净无广告的私人导航页面。 初学者:作为HTML+JavaScript静态网站开发的学习案例,熟悉基础功能集成(日历、搜索跳转)与页面布局,积累建站经验。 资源获取 免费分享石大导航网站HTML源码 - 学生专属简洁校园导航工具 下载地址:https://pan.quark.cn/s/fbc10fe3f6eb 提取码: 免费又实用,针对性强且部署简单,尤其适合学生群体使用,只需替换失效的天气插件,就能快速拥有专属简洁导航平台,值得获取体验! -
免费分享Webstack纯静态网址导航源码 - HTML响应式导航网站搭建工具 Webstack纯静态网址导航系统HTML源码:免费开源导航资源分享 给大家免费分享一款实用的网址导航类资源——Webstack纯静态大气网址导航系统HTML源码!无需付费,个人用户、初学者或需要快速搭建导航网站的使用者都能免费获取,不用复杂配置,上传服务器即可使用,不管是整理常用网址、搭建个人导航平台,还是做小型工具导航站点,都能轻松满足需求,妥妥的轻量化高效资源! mjw4sngr.png图片 一、核心资源信息 核心定位(资源核心价值):源自WordPress主题的纯静态网址导航系统,专注提供清晰的网址分类与简洁大气的前台界面,整合一言API和和风天气API,额外补充实用信息(需替换为个人API密钥,避免共享密钥导致服务中断),打造个性化导航体验。 技术与部署(资源实用性):基于HTML开发,无需数据库支持,属于绿色源码,适用于各类主机空间;无复杂后台管理系统,上传到服务器就能直接运行,部署门槛极低,初学者也能快速上手;采用响应式设计,自动适配桌面电脑、平板电脑、智能手机等不同设备屏幕尺寸,兼容IE6-IE9、Firefox、Chrome、Opera、Safari等多种浏览器,使用无兼容顾虑。 二、核心功能与特色(免费解锁便捷导航体验) (一)核心优势 响应式适配:自动匹配不同设备屏幕,不管是电脑还是手机访问,都能保持界面美观、操作便捷,满足多终端使用需求。 部署零门槛:纯静态架构,无需配置数据库和复杂环境,上传服务器即可启用,省去繁琐安装步骤,节省时间成本。 自定义性强:网页内容可通过记事本、写字板或网页编辑器直接修改,无需专业编程知识,就能轻松定制网址分类、网站样式和展示内容,适配个人或小型需求。 轻量化无负担:源码体积小巧,不占用过多主机空间,运行流畅,无惧网络攻击,稳定性有保障。 实用API整合:内置一言API和和风天气API,能在导航页面展示随机语录和天气信息,丰富网站功能,提升用户体验。 (二)存在不足 代码结构杂乱:因源自WordPress主题扒取,代码缺乏规整,需要先美化整理后,才方便后续修改和二次开发。 管理效率较低:纯静态页面无后台管理系统,后续添加、修改网址或更新内容时,需手动编辑文件,批量操作不便,不适合大规模网址管理场景。 三、资源适用场景(免费资源适配多需求) 这款免费分享的源码用途十分广泛: 个人用户:搭建专属私人导航网站,整理常用网址(如工具类、影视类、学习类),告别浏览器收藏夹杂乱,快速访问目标网站。 初学者:作为HTML静态网站开发学习案例,熟悉响应式设计、API调用等基础技能,提升实操能力;同时体验零门槛部署流程,积累建站经验。 小型需求场景:搭建小型工具导航、兴趣圈层导航(如影视资源导航、设计工具导航),满足小范围人群的集中访问需求,无需投入过多技术和服务器成本。 临时展示站点:快速搭建临时网址汇总页面,用于活动推广、团队内部资源共享等场景,部署快、维护简单。 源码获取 免费分享Webstack纯静态网址导航源码 - HTML响应式导航网站搭建工具 下载地址:https://pan.quark.cn/s/84426ecdd655 提取码: 免费又实用,轻量化部署且自定义灵活,适合追求简单高效的导航需求,若无需大规模管理,这款Webstack纯静态导航源码绝对值得入手! -
PHP代码加密工具一键批量加密 批量加密+100%开源 对PHP文件代码进行加密 加密的本质 实际上,程序于运行之际皆是在持续执行机器码,而通常情况下,基本概念里虚拟机语言的加密亦是加密至那般程度, 这意味着,PHP加密后的程序在持续执行之后皆会解密为opcode进而继续执行。 PHP在持续执行之后存在一种编程的阶段,编程所获的结果为opcode。紧接着Zend虚拟机持续执行,从这里入手倘若把源代码加密,然后在继续执行之后将代码予以解密便可。 从这儿瞧,要是代码能够被解密成opcode,这般总归有可能反向编写出源代码, 别的语言里亦是类似,就好比objdump程序能够把二进制程序反汇编出来,.NET、Java的程序也是如此,都存在不少反向编程的程序,然而通常来讲那些厂商除此之外还会 附带将代码混淆的工具,经过混淆的代码可读性非常差,好多人都留意过Gmail等网站 经过混淆的JS代码吧,自己编写生成很艰难,经过且混淆的代码就算反向编写出, 读者也极其难以通过代码去解析出代码之中的逻辑,这样也就极大地降低了应用的安全性。 调整config文件当中的数据库,依照域名/install去开展安装,如此便能够投入使用了! 202512310929213-1536x1390.webp图片 2025123109293855-1536x722.webp图片 PHP代码加密工具一键批量加密 下载地址:https://pan.baidu.com/s/1rdDXIKQ17TulDF3OgVwLig?pwd=rd16 提取码:rd16 PHP代码加密工具一键批量加密 下载地址:https://pan.quark.cn/s/8660565756a2 提取码:T13X -
雨云rainyun.com推荐 - 专属优惠码 MzM2MjI4 高性价比云服务器 实测推荐!雨云rainyun.com:高性价比云服务+专属优惠码,开发者/创业者必入 作为常年和服务器、云产品打交道的技术人,今天给大家安利一款亲测好用的云计算平台——雨云(rainyun.com),不仅产品矩阵齐全、性能稳定,还带来了专属优惠码和直达链接,新老用户都能薅福利,不管是搭建网站、部署源码,还是运行游戏服务器,都能满足需求! mjv8cgbw.png图片 一、雨云核心优势:为什么值得选? 产品丰富,一站式覆盖全场景 雨云的云产品完全能满足从个人开发者到企业的多元需求:云服务器性能强劲,支持弹性扩展,适配源码部署、网站搭建;游戏云(VPS/面板)低延迟、高稳定,玩游戏、开私服都流畅;还有裸金属物理机、显卡/网吧云、对象存储等,甚至包含域名注册、备案、免费SSL证书服务,不用跨平台折腾,一站式搞定所有云计算需求。 稳定靠谱,资质齐全有保障 作为正规云计算平台,雨云拥有《中华人民共和国增值电信业务经营许可证》(B1-20231485)、粤ICP备19052839号、粤公网安备44010302111123等完整资质,平台系统还取得了软件著作权(登记号:2023SR0336952),不用担心服务合规问题。节点监控实时可见,运行过程中几乎无宕机,技术团队响应及时,后续使用更放心。 优惠活动多,性价比拉满 除了日常的拼团优惠,雨云还推出了推广合伙人、雨创计划、润雨赞助计划等福利活动,降低使用成本。现在通过专属链接注册,再使用优惠码,还能额外享受折扣,对比同类型平台,价格优势明显,学生党、个人开发者也能轻松负担。 二、专属福利:优惠码+直达链接,省钱快人一步 专属直达链接:雨云 独家优惠码:MzM2MjI4 使用方式:打开直达链接注册雨云账号,选择心仪的云产品(云服务器、游戏云等),下单时输入优惠码MzM2MjI4,即可享受专属折扣,新用户首购更划算! 三、适用人群&使用场景推荐 开发者:部署开源源码、搭建测试环境,云服务器弹性扩展,配合免费SSL证书,快速上线个人项目; 游戏玩家/腐竹:游戏云(VPS/面板)低延迟、高带宽,支持各类游戏服务器搭建,多人联机不卡顿; 创业者/企业:裸金属物理机、对象存储满足高负载需求,域名备案、企业级安全防护一站式配齐,降低运营成本; 自媒体/站长:搭建个人博客、商业网站,稳定的节点和售后保障,确保网站全年正常访问。 四、额外加分项:细节拉满的用户体验 官方文档详细,新手也能快速上手部署,遇到问题还能通过QQ群、论坛等交流社区求助,用户和官方技术人员都会热心解答; 支持节点监控,实时查看服务器状态,还有完善的服务条款、退款政策,权益有保障; 定期更新产品功能和优惠活动,近期动态及时公示,长期使用能持续享受新福利。 总结 如果你正在寻找一款“产品全、性能稳、价格香”的云计算平台,雨云绝对值得一试!现在注册,输入优惠码MzM2MjI4,就能解锁专属折扣,不管是个人使用还是企业部署,都能省不少钱~ 亲测靠谱,赶紧冲起来! (提示:优惠活动可能有期限,建议尽早注册使用,有任何问题可联系雨云官方客服咨询~) -
免费分享意象桌面扫码点餐系统源码 - 微信小程序+H5餐饮多端运营解决方案 意象桌面扫码点餐系统源码:免费开源餐饮解决方案,多端适配助力商家高效运营 给大家免费分享一款专为餐饮行业打造的全能型开源资源——意象桌面扫码点餐系统源码!无需付费,个体餐饮商户、连锁品牌、餐饮创业者以及开发者都能免费获取,不管是搭建扫码点餐平台、拓展外卖与自取业务,还是实现会员营销与多门店统一管理,都能一站式满足需求,妥妥的餐饮行业降本增效利器! mjunri92.png图片 一、核心资源信息 核心定位(资源核心价值):聚焦餐饮全业务场景,提供从用户点餐到商家运营的完整闭环解决方案,覆盖扫码点餐、在线外卖、到店自取、提前预约、会员管理、营销推广等核心需求,帮助餐饮商家摆脱传统点餐模式的低效束缚,实现数字化、智能化运营,提升服务效率与客户体验。 技术架构(资源硬核配置):采用前后端分离架构,技术栈先进且成熟稳定,适配各类部署场景—— 后端:基于Spring Boot 3构建核心框架,搭配Spring Security OAuth2权限认证、MyBatis Plus数据访问、Redis缓存优化、JWT安全验证,同时整合Lombok、Hutool等实用工具,大幅提升开发效率与系统性能; 前端:PC端后台管理界面采用Vue3 + Element UI开发,界面清晰、操作便捷;移动端通过uni-app(Vue3)实现,无缝适配微信小程序与H5页面,覆盖用户主流访问场景; 项目结构:模块化划分明确,包含后端Java工程、后台管理前端工程、移动端uni-app工程,代码注释完善、逻辑清晰,便于理解与二次开发。 部署与适配(资源实用优势):支持本地服务器快速部署、云平台部署以及私有化部署,满足不同商家的服务器配置需求;兼容JDK 17、MySQL 8、Redis 6+、Node.js 16+等主流开发环境,搭配IDEA、VSCode、HBuilder等常用开发工具即可快速启动项目;同时支持SaaS多租户架构,既能满足个体商户的单门店运营,也能适配连锁品牌的多门店统一管理需求。 二、核心功能资源(免费解锁餐饮全场景运营能力) (一)用户端功能(微信小程序/H5双端支持) 灵活点餐模式:支持桌面扫码点餐,单人点餐高效便捷,多人协同点餐互不干扰,无需服务员手动记录,减少沟通成本;同时提供外卖配送与到店自取两种选择,用户可根据需求自由切换,外卖模式支持物流信息实时查看,自取模式无需排队等待,提升用餐体验。 丰富商品展示:支持多规格商品(SKU)管理,商品详情页包含图文介绍、价格、库存等信息,分类清晰(如新品推荐、招牌热卖、主食、饮品等),用户可快速找到心仪菜品,下单更直观。 多元支付与订单管理:支持微信支付、余额支付、积分+金额混合支付等多种支付方式,满足不同用户的支付习惯;用户可随时查看历史订单、当前订单状态(待支付、待出单、待收货、已完成等),订单信息一目了然,还能便捷处理退款申请。 完善会员体系:用户可维护个人信息、管理收货地址,查看积分明细与优惠券;积分可用于兑换商品或抵扣订单金额,优惠券支持领取与核销,增强用户粘性与复购意愿;同时提供余额充值功能,支持微信支付充值,方便用户快速下单支付。 提前预约功能:用户可提前预约到店时间,商家提前做好备餐准备,避免到店后长时间等待,提升用餐效率,尤其适合高峰时段用餐需求。 (二)商家后台功能(PC端专属管理) 商品与店铺管理:支持商品添加、编辑、上下架操作,可灵活配置商品规格、分类与图文详情;支持多门店信息维护,连锁品牌可统一管理旗下所有门店,独立设置各门店的商品、价格、配送范围等参数;内置图片素材库,商品图片、轮播图等素材可统一存储与管理,方便快速调用。 订单与桌台管理:实时查看所有订单信息,支持订单状态更新(接单、出单、完成、退款等)、订单打印,对接云打印机可实现小票自动打印,提升出单效率;支持桌号配置、扫码绑定桌台,实时查看桌台占用状态(空闲、已点餐、用餐中、已结账),便于合理安排座位,优化店内运营流程。 会员与营销管理:可设置会员等级、积分规则,查看会员充值记录、消费明细,支持黑名单管理,精准筛选优质客户;提供丰富的营销工具,包括优惠券创建与发放、充值活动配置(如充值送积分、送优惠券),助力商家吸引新客户、留住老客户,提升营业额。 收银与数据管理:内置收银台功能,支持扫码枪、扫码盒子等设备收款,适配线下门店直接收银场景;实时统计今日营业额、订单数量、访客人数、退单数量等核心数据,商家可直观掌握门店运营状况,为经营决策提供数据支持。 微信公众号对接:支持微信公众号关注引导、自定义菜单配置,可向用户推送订单通知、活动公告等消息,增强与用户的互动,提升品牌曝光与用户活跃度。 (三)技术支撑功能(保障系统稳定高效运行) 安全机制:采用JWT认证与OAuth2安全框架,保障用户信息与交易数据的传输安全;严格的权限控制体系,不同角色(管理员、门店操作员等)分配专属权限,避免数据误操作。 性能优化:通过Redis缓存热点数据(如商品信息、会员积分等),减少数据库查询压力,提升系统响应速度,即使高峰时段多用户同时点餐也能保持流畅。 开发便捷:整合Lombok、Hutool等工具简化代码编写,开发环境配置清晰,本地部署流程简单,开发者可快速搭建开发环境,开展二次开发工作。 三、资源特色(免费资源优势拉满) 技术先进且稳定:基于Spring Boot 3、Vue3等主流技术栈构建,架构设计合理,兼容性强、扩展性好,能够适应餐饮行业的业务变化与规模扩张,长期使用无后顾之忧。 多场景全面适配:覆盖扫码点餐、外卖、自取、预约、会员营销、多门店管理等餐饮核心场景,无论是快餐店、饮品店、特色餐厅,还是连锁餐饮品牌,都能精准匹配需求。 开源免费无套路:采用MIT License开源协议,完全开源可商用,无强制保留作者信息或版权信息的要求,商家可直接部署使用,开发者可自由修改、定制功能,大幅降低开发与运营成本。 可定制性极强:代码结构清晰、模块化设计合理,附带完善注释与相关文档,二次开发门槛低,商家可根据自身业务特点添加特色功能(如专属营销活动、定制化支付方式等),开发者可基于源码拓展更多餐饮相关功能,打造个性化解决方案。 运营效率翻倍:通过数字化点餐流程减少人工干预,降低服务员工作量与人为失误;多端协同与实时数据统计让商家运营管理更高效,会员营销工具助力提升用户复购与营业额,全方位为餐饮商家降本增效。 四、资源适用场景(免费资源适配多类需求) 这款免费分享的意象桌面扫码点餐系统源码,适用场景十分广泛: 个体餐饮商户(快餐店、饮品店、小吃店等):快速搭建扫码点餐平台,减少人工点餐压力,提升翻台率;支持外卖与自取业务,拓展销售渠道,增加营收来源。 连锁餐饮品牌:借助SaaS多租户架构实现多门店统一管理,同步商品信息、营销活动,实时监控各门店运营数据,规范品牌运营标准,降低管理成本。 餐饮创业者:无需投入高额资金开发定制系统,直接基于源码快速搭建专属点餐平台,缩短项目上线周期,聚焦核心产品与服务,提升创业成功率。 开发者/技术团队:作为餐饮行业系统开发的参考案例,学习前后端分离架构、多端适配、权限管理等技术实现;或基于源码二次开发,为餐饮客户提供定制化解决方案,提升项目交付效率。 餐饮行业服务商:整合源码功能,为合作餐饮商家提供一站式数字化运营解决方案,涵盖点餐、会员、营销等模块,增强服务竞争力。 下载 下载点餐小程序源码 下载地址:https://pan.quark.cn/s/b8b58d03cbb2 提取码: 免费又实用,功能全面且技术成熟,不管是直接部署使用,还是二次开发定制专属功能,这款意象桌面扫码点餐系统源码都能为餐饮行业从业者带来实实在在的价值,强烈推荐获取体验! -
字节曜博客 2026 元旦快乐!愿技术同行新岁顺意,万事可期 元旦快乐!愿新岁如朝阳,温暖而明亮 元旦的钟声已经敲响,时光的年轮又增添了新的一圈。在这辞旧迎新的时刻,我谨向所有字节曜博客的读者们致以最诚挚的祝福:元旦快乐,万事胜意! mju9a26l.png图片 一、岁序更替:告别与迎接的仪式感 站在2026年的门槛上,我们不禁回望刚刚过去的一年。那些欢笑与泪水,成功与挑战,都已沉淀为生命中宝贵的财富。旧岁已展千重锦,新年再进百尺竿。元旦,不仅仅是一个时间节点,更是一个充满仪式感的新起点,让我们有机会重新审视自己,整理行囊,带着希望与梦想再次出发。 二、新年新愿:多元祝福送给特别的你 1. 愿你如阳光般明媚 新的一年,愿阳光洒满你的每一天,温暖而不刺眼。愿你的笑容如春日般灿烂,烦恼如冰雪般消融。当生活偶尔阴霾,请记得:你本就是自己生命中最耀眼的光芒。 2. 愿你如星辰般璀璨 在追求梦想的道路上,愿你像夜空中的星辰一样,既保持自己独特的光芒,又与周围的世界和谐共处。愿你的努力被看见,付出有回报,在属于自己的领域里闪闪发光。 3. 愿你如流水般从容 面对生活的起伏跌宕,愿你拥有流水般的智慧:遇山绕行,遇石分流,始终保持前进的方向。学会在忙碌中寻找安宁,在挑战中锤炼韧性,在变化中把握机遇。 4. 愿你如大地般厚实 新的一年,愿你拥有坚实的根基和广阔的胸怀。像大地一样,默默耕耘,静待花开;像大地一样,包容万物,涵养生命。愿你的内心充满力量,足以支撑你走过每一段路程。 三、字节同行:技术赋能,共赴新程 作为字节曜博客的编辑,我特别想对所有技术爱好者说:2026年,让我们继续在技术的海洋中探索,在代码的世界里创造。愿我们的每一行代码都能解决实际问题,每一个创新都能带来真实价值,每一次分享都能点亮他人的智慧。 在这个AI与大数据交织的时代,愿我们保持"Always Day 1"的初心,不断学习,持续成长,用技术的力量为世界增添美好。 四、结语:携手同行,未来可期 元旦的意义,不仅在于迎接新的一年,更在于我们对未来的共同期待。愿2026年的每一个日子,都能带给你新的惊喜和成长;愿我们在字节曜博客这个平台上,继续分享知识,交流思想,共同进步。 最后,再次祝愿大家:元旦快乐,阖家幸福,身体安康,万事顺遂! 让我们一起,以饱满的热情迎接充满希望的2026年! -
免费分享bujuan开源播放器 - 安卓第三方网易云音乐轻量工具(跨平台) bujuan开源音乐播放器:安卓端免费第三方网易云工具分享 给大家免费分享一款专注音乐体验的播放器资源——bujuan开源第三方网易云音乐播放器!无需付费,网易云音乐爱好者、开发者都能免费获取,安卓用户可直接下载使用,它去除冗余功能、聚焦核心播放体验,不管是日常听歌,还是开发者学习二次开发,都是性价比超高的优质资源! mju3e9tq.png图片 一、核心资源信息 核心定位(资源核心价值):专为网易云音乐用户打造的第三方播放器,专注核心音乐播放功能,剔除原生APP中不必要的社交、视频等冗余模块,让界面更简洁、操作更流畅,沉浸式享受音乐。 技术与适配(资源实用性):基于Flutter框架开发,具备超强跨平台兼容性,支持Android、iOS、Windows、macOS、Linux五大系统(目前官方仅提供安卓APP下载);项目目录结构清晰,包含多平台支持文件,技术成熟且易扩展。 二、核心功能与特色(免费解锁纯粹音乐体验) 便捷账号登录:支持手机号登录和二维码扫码登录两种方式,直接关联网易云音乐账号,无需额外注册,快速同步个人音乐数据。 核心播放功能:覆盖网易云核心音乐服务,包括每日推荐、私人FM、电台播放、云盘歌曲播放,满足日常听歌的各类需求;还能按歌曲、专辑、歌手精准搜索,快速找到想听的音乐。 个性化推荐:内置智能推荐系统,基于用户听歌习惯推送契合口味的音乐,像私人雷达、歌单推荐等功能,精准捕捉音乐偏好。 多平台统一体验:依托Flutter框架优势,不同系统上的界面风格、操作逻辑保持一致,不管后续切换到iOS、Windows等平台,都能快速适应。 开源可定制:项目代码完全开源,开发者可自由修改、定制功能,或打包适配其他平台,适合作为Flutter开发学习案例,也能二次开发打造专属播放器。 轻量中文友好:体积轻巧不占过多设备内存,中文界面简洁直观,国内用户使用无门槛,上手就能顺畅操作。 三、资源适用场景(免费资源适配多需求) 这款免费分享的播放器资源,用途十分广泛: 网易云音乐爱好者:想摆脱原生APP冗余功能,追求纯粹听歌体验,用它能专注音乐本身,界面干净、操作流畅。 跨平台需求用户:后续计划在iOS、Windows、macOS、Linux等设备上使用统一播放器,可等待官方版本或自行编译,实现多设备音乐体验同步。 开发者:学习Flutter跨平台开发技术,研究音乐播放器的功能实现逻辑;或基于开源代码二次开发,添加个性化功能、定制界面风格。 获取APP bujuan播放器 下载地址:https://pan.quark.cn/s/49a886393fee 提取码: 免费又纯粹,专注音乐体验且支持多平台扩展,不管是普通用户日常听歌,还是开发者学习实践,这款bujuan开源播放器都值得一试!