【开源工具】Python+PyQt5打造智能桌面单词记忆工具:悬浮窗+热键切换+自定义词库

article/2025/6/7 14:22:53

📚【深度解析】Python+PyQt5打造智能桌面单词记忆工具:悬浮窗+热键切换+自定义词库

在这里插入图片描述
请添加图片描述

🌈 个人主页:创客白泽 - CSDN博客
🔥 系列专栏:🐍《Python开源项目实战》
💡 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。
👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

请添加图片描述

在这里插入图片描述

一、概述:当单词记忆遇上Python GUI

在英语学习过程中,高频重复是记忆单词的关键。传统背单词软件往往需要用户主动打开应用,而本项目的创新之处在于开发了一个桌面悬浮窗单词记忆工具,具有以下核心特点:

  • 无干扰学习:半透明悬浮窗始终置顶显示
  • 智能记忆算法:支持顺序/逆序/随机三种循环模式
  • 快捷交互:F8热键一键切换中英释义
  • 高度可定制:字体/颜色/间隔时间全面可配置
  • 轻量化设计:系统托盘运行,内存占用<50MB

本文将深入解析200+行代码的实现原理,并提供完整的可执行方案。

二、功能架构设计

在这里插入图片描述

2.1 核心功能模块

  1. 单词显示模块

    • 定时切换显示
    • 中英双语切换
    • 视觉样式定制
  2. 交互控制模块

    • 全局热键监听
    • 拖拽移动窗口
    • 系统托盘菜单
  3. 配置管理模块

    • QSettings持久化
    • 词库动态加载
    • 设置实时生效

2.2 技术选型对比

技术方案优势本项目选择原因
PyQt5成熟GUI框架跨平台支持好
pynput全局热键监听比win32api更简洁
QSettings配置存储无需额外数据库

三、效果展示

3.1 主界面效果

在这里插入图片描述

3.2 设置面板

在这里插入图片描述

3.3 系统托盘菜单

在这里插入图片描述

四、实现步骤详解

4.1 环境准备

pip install PyQt5 pynput

4.2 词库文件格式

创建words.txt(每行一个单词+释义):

apple 苹果
banana 香蕉

4.3 核心类解析

4.3.1 热键监听线程
class HotkeyWorker(QObject):toggle_signal = pyqtSignal()def run(self):from pynput import keyboarddef on_activate_f8():self.toggle_signal.emit()with keyboard.GlobalHotKeys({'<F8>': on_activate_f8}) as listener:listener.join()

关键点

  • 使用QObject实现跨线程信号通信
  • pynput库实现全局热键监听
  • 异常处理保障稳定性
4.3.2 主窗口类
class WordDisplayApp(QMainWindow):def __init__(self):super().__init__()self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)self.setAttribute(Qt.WA_TranslucentBackground)

窗口特性

  • FramelessWindowHint:无边框
  • WindowStaysOnTopHint:始终置顶
  • WA_TranslucentBackground:半透明效果

4.4 配置持久化实现

self.settings = QSettings("WordDisplay", "WordDisplayApp")# 保存配置
self.settings.setValue("interval", self.interval)# 读取配置
self.interval = self.settings.value("interval", 5, type=int)

存储位置

  • Windows:注册表HKEY_CURRENT_USER\Software\WordDisplay\WordDisplayApp
  • Mac:~/Library/Preferences/com.WordDisplay.WordDisplayApp.plist

五、代码深度解析

5.1 单词加载算法

def load_words(self):if self.order == "reverse":self.word_list.reverse()elif self.order == "random":random.shuffle(self.word_list)

记忆算法优化

  • 随机模式:避免固定顺序记忆
  • 逆序模式:强化尾部单词记忆
  • 间隔重复:通过定时器控制显示节奏

5.2 拖拽移动实现

def mousePressEvent(self, event):self.dragging = Trueself.offset = event.globalPos() - self.pos()def mouseMoveEvent(self, event):if self.dragging:self.move(event.globalPos() - self.offset)

交互细节

  • 记录鼠标点击位置与窗口位置的偏移量
  • 实时计算新窗口位置
  • 鼠标释放时重置状态

5.3 系统托盘集成

self.tray_icon = QSystemTrayIcon(self)
tray_menu = QMenu()
exit_action = QAction("退出", self)
exit_action.triggered.connect(self.quit_app)
tray_menu.addAction(exit_action)

多平台适配

  • Windows/Mac/Linux通用实现
  • 双击图标显示/隐藏窗口
  • 右键弹出功能菜单

六、完整源码下载

import sys
import random
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QSystemTrayIcon,QMenu, QAction, QWidget, QVBoxLayout, QPushButton,QSpinBox, QComboBox, QColorDialog, QMessageBox, QDesktopWidget, QFileDialog)
from PyQt5.QtGui import QColor, QFont, QIcon, QPixmap, QCursor
from PyQt5.QtCore import Qt, QTimer, QSettings, QSize, QThread, pyqtSignal, QObject, QPointclass HotkeyWorker(QObject):"""处理全局快捷键的工作线程"""toggle_signal = pyqtSignal()error_signal = pyqtSignal(str)def __init__(self):super().__init__()self.listener = Nonedef run(self):"""启动热键监听"""try:from pynput import keyboarddef on_activate_f8():self.toggle_signal.emit()with keyboard.GlobalHotKeys({'<F8>': on_activate_f8}) as self.listener:self.listener.join()except ImportError as e:self.error_signal.emit("未安装pynput库,无法使用F8快捷键功能")except Exception as e:self.error_signal.emit(f"快捷键初始化失败: {str(e)}")def stop(self):"""停止热键监听"""if self.listener:self.listener.stop()class WordDisplayApp(QMainWindow):def __init__(self):super().__init__()# 初始化设置self.settings = QSettings("WordDisplay", "WordDisplayApp")self.load_settings()# 初始化UIself.init_ui()# 加载单词数据self.word_list = []self.current_word_file = "words.txt"  # 默认词库文件self.load_words()# 设置当前单词索引self.current_index = 0# 显示第一个单词self.show_word()# 设置定时器self.timer = QTimer()self.timer.timeout.connect(self.show_next_word)self.timer.start(self.interval * 1000)# 中文释义是否显示self.show_translation = False# 初始化热键线程self.init_hotkey_thread()# 拖动相关变量self.dragging = Falseself.offset = QPoint()def init_hotkey_thread(self):"""初始化热键监听线程"""self.hotkey_thread = QThread()self.hotkey_worker = HotkeyWorker()self.hotkey_worker.moveToThread(self.hotkey_thread)# 连接信号self.hotkey_worker.toggle_signal.connect(self.toggle_translation)self.hotkey_worker.error_signal.connect(self.show_error_message)# 启动线程self.hotkey_thread.started.connect(self.hotkey_worker.run)self.hotkey_thread.start()def show_error_message(self, message):"""显示错误消息"""QMessageBox.warning(self, "警告", message)def init_ui(self):"""初始化用户界面"""self.setWindowTitle("单词显示")self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)self.setAttribute(Qt.WA_TranslucentBackground)# 创建主部件main_widget = QWidget()self.setCentralWidget(main_widget)# 布局layout = QVBoxLayout()layout.setContentsMargins(10, 10, 10, 10)main_widget.setLayout(layout)# 英文单词标签self.word_label = QLabel("单词加载中...")self.word_label.setAlignment(Qt.AlignCenter)self.word_label.setFont(QFont("Arial", self.english_font_size))self.word_label.setStyleSheet(f"color: {self.word_color.name()};")# 中文翻译标签self.translation_label = QLabel()self.translation_label.setAlignment(Qt.AlignCenter)self.translation_label.setFont(QFont("微软雅黑", self.chinese_font_size))self.translation_label.setStyleSheet(f"color: {self.translation_color.name()};")self.translation_label.hide()# 添加到布局layout.addWidget(self.word_label)layout.addWidget(self.translation_label)# 系统托盘图标self.init_system_tray()# 移动到右上角self.move_to_top_right()def init_system_tray(self):"""初始化系统托盘图标"""self.tray_icon = QSystemTrayIcon(self)# 设置图标icon_path = os.path.join(os.path.dirname(__file__), "icon.ico")if os.path.exists(icon_path):self.tray_icon.setIcon(QIcon(icon_path))else:# 创建默认图标pixmap = QPixmap(QSize(64, 64))pixmap.fill(Qt.transparent)self.tray_icon.setIcon(QIcon(pixmap))QMessageBox.warning(self, "图标未找到", f"未找到图标文件: {icon_path}")# 创建托盘菜单tray_menu = QMenu()# 显示/隐藏主窗口toggle_action = QAction("显示/隐藏", self)toggle_action.triggered.connect(self.toggle_visibility)tray_menu.addAction(toggle_action)# 重置位置reset_pos_action = QAction("重置位置", self)reset_pos_action.triggered.connect(self.move_to_top_right)tray_menu.addAction(reset_pos_action)# 设置settings_action = QAction("设置", self)settings_action.triggered.connect(self.show_settings_dialog)tray_menu.addAction(settings_action)# 加载词库load_dict_action = QAction("加载词库", self)load_dict_action.triggered.connect(self.load_new_dictionary)tray_menu.addAction(load_dict_action)# 退出exit_action = QAction("退出", self)exit_action.triggered.connect(self.quit_app)tray_menu.addAction(exit_action)self.tray_icon.setContextMenu(tray_menu)self.tray_icon.show()# 托盘图标点击事件self.tray_icon.activated.connect(self.on_tray_icon_activated)def on_tray_icon_activated(self, reason):"""托盘图标点击事件处理"""if reason == QSystemTrayIcon.DoubleClick:self.toggle_visibility()def move_to_top_right(self):"""将窗口移动到屏幕右上角"""screen = QDesktopWidget().screenGeometry()self.move(screen.width() - self.width() - 20, 20)def mousePressEvent(self, event):"""鼠标按下事件"""if event.button() == Qt.LeftButton:self.dragging = Trueself.offset = event.globalPos() - self.pos()event.accept()self.setCursor(QCursor(Qt.SizeAllCursor))def mouseMoveEvent(self, event):"""鼠标移动事件"""if self.dragging and event.buttons() & Qt.LeftButton:self.move(event.globalPos() - self.offset)event.accept()def mouseReleaseEvent(self, event):"""鼠标释放事件"""if event.button() == Qt.LeftButton:self.dragging = Falseself.setCursor(QCursor(Qt.ArrowCursor))event.accept()def load_words(self, file_path=None):"""从文件加载单词数据"""try:if file_path is None:file_path = self.current_word_filewith open(file_path, "r", encoding="utf-8") as f:self.word_list = []for line in f:line = line.strip()if line:parts = line.split(maxsplit=1)if len(parts) == 2:self.word_list.append({"word": parts[0],"translation": parts[1]})# 根据顺序设置处理单词列表if self.order == "reverse":self.word_list.reverse()elif self.order == "random":random.shuffle(self.word_list)if not self.word_list:self.word_list.append({"word": "示例单词","translation": "example translation"})except FileNotFoundError:QMessageBox.critical(self, "错误", f"未找到词库文件: {file_path}")self.word_list = [{"word": "示例单词","translation": "example translation"}]except Exception as e:QMessageBox.critical(self, "错误", f"加载词库失败: {str(e)}")self.word_list = [{"word": "加载失败","translation": "load failed"}]def load_new_dictionary(self):"""加载新的词库文件"""file_path, _ = QFileDialog.getOpenFileName(self, "选择词库文件", "", "文本文件 (*.txt);;所有文件 (*)")if file_path:self.current_word_file = file_pathself.load_words(file_path)self.current_index = 0self.show_word()# 保存当前词库路径self.settings.setValue("current_word_file", file_path)def show_word(self):"""显示当前单词"""if not self.word_list:returnword_data = self.word_list[self.current_index]self.word_label.setText(word_data["word"])self.translation_label.setText(word_data["translation"])def show_next_word(self):"""显示下一个单词"""if not self.word_list:returnif self.order == "random":self.current_index = random.randint(0, len(self.word_list) - 1)else:self.current_index += 1if self.current_index >= len(self.word_list):self.current_index = 0self.show_word()def toggle_translation(self):"""切换翻译显示状态"""self.show_translation = not self.show_translationself.translation_label.setVisible(self.show_translation)# 根据翻译显示状态控制定时器if self.show_translation:self.timer.stop()  # 显示翻译时暂停计时器else:self.timer.start(self.interval * 1000)  # 隐藏翻译时恢复计时器def show_settings_dialog(self):"""显示设置对话框"""self.settings_dialog = QWidget()self.settings_dialog.setWindowTitle("设置")self.settings_dialog.setWindowModality(Qt.ApplicationModal)self.settings_dialog.setFixedSize(350, 450)layout = QVBoxLayout()layout.setContentsMargins(10, 10, 10, 10)# 间隔时间设置interval_label = QLabel("显示间隔(秒):")self.interval_spinbox = QSpinBox()self.interval_spinbox.setRange(1, 3600)self.interval_spinbox.setValue(self.interval)# 单词顺序设置order_label = QLabel("单词顺序:")self.order_combobox = QComboBox()self.order_combobox.addItems(["顺序", "逆序", "随机"])self.order_combobox.setCurrentIndex(["normal", "reverse", "random"].index(self.order))# 英文字体大小设置english_fontsize_label = QLabel("英文单词字体大小:")self.english_fontsize_spinbox = QSpinBox()self.english_fontsize_spinbox.setRange(8, 72)self.english_fontsize_spinbox.setValue(self.english_font_size)# 中文字体大小设置chinese_fontsize_label = QLabel("中文翻译字体大小:")self.chinese_fontsize_spinbox = QSpinBox()self.chinese_fontsize_spinbox.setRange(8, 72)self.chinese_fontsize_spinbox.setValue(self.chinese_font_size)# 单词颜色设置word_color_label = QLabel("单词颜色:")self.word_color_button = QPushButton()self.word_color_button.setStyleSheet(f"background-color: {self.word_color.name()};")self.word_color_button.clicked.connect(lambda: self.choose_color("word"))# 翻译颜色设置trans_color_label = QLabel("翻译颜色:")self.trans_color_button = QPushButton()self.trans_color_button.setStyleSheet(f"background-color: {self.translation_color.name()};")self.trans_color_button.clicked.connect(lambda: self.choose_color("translation"))# 保存按钮save_button = QPushButton("保存设置")save_button.clicked.connect(self.save_settings)# 重新加载当前词库按钮reload_button = QPushButton("重新加载当前词库")reload_button.clicked.connect(lambda: self.load_words(self.current_word_file))# 添加到布局layout.addWidget(interval_label)layout.addWidget(self.interval_spinbox)layout.addWidget(order_label)layout.addWidget(self.order_combobox)layout.addWidget(english_fontsize_label)layout.addWidget(self.english_fontsize_spinbox)layout.addWidget(chinese_fontsize_label)layout.addWidget(self.chinese_fontsize_spinbox)layout.addWidget(word_color_label)layout.addWidget(self.word_color_button)layout.addWidget(trans_color_label)layout.addWidget(self.trans_color_button)layout.addWidget(save_button)layout.addWidget(reload_button)layout.addStretch()self.settings_dialog.setLayout(layout)self.settings_dialog.show()def choose_color(self, color_type):"""选择颜色"""color = QColorDialog.getColor()if color.isValid():if color_type == "word":self.word_color = colorself.word_color_button.setStyleSheet(f"background-color: {color.name()};")else:self.translation_color = colorself.trans_color_button.setStyleSheet(f"background-color: {color.name()};")def save_settings(self):"""保存设置"""self.interval = self.interval_spinbox.value()order_index = self.order_combobox.currentIndex()if order_index == 0:self.order = "normal"elif order_index == 1:self.order = "reverse"else:self.order = "random"self.english_font_size = self.english_fontsize_spinbox.value()self.chinese_font_size = self.chinese_fontsize_spinbox.value()# 保存到QSettingsself.settings.setValue("interval", self.interval)self.settings.setValue("order", self.order)self.settings.setValue("english_font_size", self.english_font_size)self.settings.setValue("chinese_font_size", self.chinese_font_size)self.settings.setValue("word_color", self.word_color.name())self.settings.setValue("translation_color", self.translation_color.name())# 应用设置self.apply_settings()self.settings_dialog.close()def apply_settings(self):"""应用当前设置"""# 更新定时器间隔self.timer.stop()if not self.show_translation:  # 只有隐藏翻译时才启动计时器self.timer.start(self.interval * 1000)# 更新字体大小self.word_label.setFont(QFont("Arial", self.english_font_size))self.translation_label.setFont(QFont("微软雅黑", self.chinese_font_size))# 更新颜色self.word_label.setStyleSheet(f"color: {self.word_color.name()};")self.translation_label.setStyleSheet(f"color: {self.translation_color.name()};")# 如果需要,重新排序单词if self.order == "reverse":self.word_list.reverse()elif self.order == "random":random.shuffle(self.word_list)# 重置索引self.current_index = 0self.show_word()def toggle_visibility(self):"""切换窗口可见性"""if self.isVisible():self.hide()else:self.show()self.move_to_top_right()def quit_app(self):"""退出应用程序"""# 停止热键线程if hasattr(self, 'hotkey_thread'):self.hotkey_worker.stop()self.hotkey_thread.quit()self.hotkey_thread.wait()# 保存设置self.settings.sync()QApplication.quit()def closeEvent(self, event):"""重写关闭事件"""event.ignore()self.hide()def load_settings(self):"""加载设置"""# 默认设置self.interval = self.settings.value("interval", 5, type=int)self.order = self.settings.value("order", "normal")self.english_font_size = self.settings.value("english_font_size", 24, type=int)self.chinese_font_size = self.settings.value("chinese_font_size", 20, type=int)self.current_word_file = self.settings.value("current_word_file", "words.txt")# 颜色设置self.word_color = QColor(self.settings.value("word_color", "#000000"))self.translation_color = QColor(self.settings.value("translation_color", "#888888"))if __name__ == "__main__":app = QApplication(sys.argv)app.setQuitOnLastWindowClosed(False)# 设置应用程序图标icon_path = os.path.join(os.path.dirname(__file__), "icon.ico")if os.path.exists(icon_path):app.setWindowIcon(QIcon(icon_path))word_app = WordDisplayApp()word_app.hide()sys.exit(app.exec_())

项目结构:

word-display/
├── main.py            # 主程序
├── words.txt          # 示例词库
├── icon.ico           # 程序图标
└── requirements.txt   # 依赖库

七、扩展开发建议

7.1 功能增强方向

  1. 记忆曲线算法:根据艾宾浩斯曲线调整单词出现频率
  2. 云端同步:增加词库网络同步功能
  3. 发音功能:集成TTS引擎朗读单词

7.2 性能优化建议

# 使用LRU缓存最近显示的单词
from functools import lru_cache@lru_cache(maxsize=50)
def get_word_style(word):return generate_style(word)

八、总结

本文详细解析了基于PyQt5的单词记忆工具开发全过程,关键技术点包括:

  1. 多线程热键监听的实现方案
  2. QSettings配置持久化的最佳实践
  3. 无边框窗口的交互细节处理
  4. 系统托盘应用的开发模式

该项目的创新价值在于:

  • 被动记忆转化为主动感知
  • 极简主义设计哲学的应用
  • 可扩展的架构设计

“The limits of my language mean the limits of my world.” - Ludwig Wittgenstein

通过这个项目,我们不仅学习了PyQt5开发技巧,更创造了一个真正能提升学习效率的工具。期待读者基于此项目开发出更多有趣的应用!


相关资源推荐

  • PyQt5官方文档
  • pynput高级用法
  • QSS样式表语法

问题交流:欢迎在评论区留言讨论!


http://www.hkcw.cn/article/jVMRWiOQIp.shtml

相关文章

第二十二章 Shell脚本入门

第二十二章 Shell脚本入门 Shell脚本就是包含一系列命令的文件。Shell读取该文件并执行其中的命令&#xff0c;Shell的独特之处在于它即使系统强大的命令接口&#xff0c;又是脚本语言解释器。 创建并执行Shell脚本 创建并执行脚本&#xff0c;要做到3件事: 编写脚本。将脚…

Pandas取代Excel?

有人在知乎上提问&#xff1a;为什么大公司不用pandas取代excel&#xff1f; 而且列出了几个理由&#xff1a;Pandas功能比Excel强大&#xff0c;运行速度更快&#xff0c;Excel除了简单和可视化界面外&#xff0c;没有其他更多的优势。 有个可怕的现实是&#xff0c;对比Exce…

网络安全运维实训室建设方案

一、网络安全运维人才需求与实训困境 在数字化时代&#xff0c;网络安全已成为国家安全、社会稳定和经济发展的重要基石。随着信息技术的飞速发展&#xff0c;网络安全威胁日益复杂多样&#xff0c;从个人隐私泄露到企业商业机密被盗&#xff0c;从关键基础设施遭受攻击到社会…

【C++篇】STL适配器(下篇):优先级队列与反向迭代器的底层奥秘

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…

在使用十字滑台的过程中,我们需要注意哪些关键事项呢

在使用十字滑台的过程中&#xff0c;需要注意以下关键事项&#xff1a; 安全操作&#xff1a;在使用十字滑台时&#xff0c;务必要注意安全&#xff0c;戴好手套和护目镜&#xff0c;避免发生意外伤害。 稳定支撑&#xff1a;确保十字滑台稳固地放置在平坦稳定的表面上&#x…

【笔记】用命令手动下载并安装 tokenizers 库.whl文件(Python 3.12+)

Python 3.12 虚拟环境中安装 tokenizers 教程笔记 在 Python 3.12 虚拟环境中安装 tokenizers 库时&#xff0c;我们可能会遇到pip install tokenizers安装失败和找不到适配版本的公开 whl 文件&#xff0c;从而导致tokenizers库缺失的问题。 经过探索&#xff0c;我们找到了…

光子器件仿真软件基础与基于优化方法的器件逆向设计---案例片上米散射结构色超构表面单元仿真

以下为针对片上米散射结构色超构表面单元仿真的技术要点和方法整理&#xff1a; 仿真流程框架 import meep as mp import numpy as np # 创建超构表面单元模型 cell_size mp.Vector3(1, 1, 0) geometry [mp.Cylinder(height0.5, radius0.2, materialmp.Medium(index3.5))] …

软件工程的定义与发展历程

文章目录 一、软件工程的定义二、软件工程的发展历程1. 前软件工程时期(1940s-1960s)2. 软件工程诞生(1968)3. 结构化方法时期(1970s)4. 面向对象时期(1980s)5. 现代软件工程(1990s-至今) 三、软件工程的发展趋势 一、软件工程的定义 软件工程是应用系统化、规范化、可量化的方…

基于SDN环境下的DDoS异常攻击的检测与缓解

参考以下两篇博客&#xff0c;最后成功&#xff1a; 基于SDN的DDoS攻击检测和防御方法_基于sdn的ddos攻击检测与防御-CSDN博客 利用mininet模拟SDN架构并进行DDoS攻击与防御模拟&#xff08;Ryumininetsflowpostman&#xff09;_mininet模拟dos攻击-CSDN博客 需求 H2 模拟f…

VS下C++及C#项目打包发布方法

一.打包为单一exe文件 1.打开项目属性页&#xff08;右键项目 → 属性&#xff09; 2.选择配置&#xff08;如 Release&#xff09; 3.项目属性→ C/C → 代码生成→ 运行库 将 运行时库&#xff08;Runtime Library&#xff09; 设置为&#xff1a; /MT&#xff08;Release 模…

【免费】2004-2020年各省电力消费量数据

2004-2020年各省电力消费量数据 1、时间&#xff1a;2004-2020年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区、年份、电力消费量(亿千瓦小时) 4、范围&#xff1a;31省 5、指标说明&#xff1a;电力消费量是指在一定时期内&#xff…

[Python] python信号处理绘制信号频谱

python信号处理绘制信号频谱&#xff1a;scipy.signal.welch 文章目录 python信号处理绘制信号频谱&#xff1a;scipy.signal.welch一、函数介绍二、核心参数详解三、返回值四、算法原理五、关键特性六、完整示例七、应用场景推荐配置八、常见问题解决九、与FFT方法的对比 scip…

【图像处理入门】4. 图像增强技术——对比度与亮度的魔法调节

摘要 图像增强是改善图像视觉效果的核心技术。本文将详解两种基础增强方法&#xff1a;通过直方图均衡化拉伸对比度&#xff0c;以及利用伽马校正调整非线性亮度。结合OpenCV代码实战&#xff0c;学会处理灰度图与彩色图的不同增强策略&#xff0c;理解为何彩色图像需在YUV空间…

Mybatis--创建mapper接口

创建mapper接口 MyBatis中的mapper接口相当于以前的dao&#xff08;原来的dao是有dao的接口以及dao的实现类&#xff09;。但是区别在于&#xff0c;mapper仅仅是接口&#xff0c;我们不需要提供实现类。因为我们的mybatis里面有面向接口编程&#xff0c;只需要创建mapper接口…

vue3:Table组件动态的字段(列)权限、显示隐藏和左侧固定

效果展示 根据后端接口返回&#xff0c;当前登录用户详情中的页面中el-table组件的显示隐藏等功能。根据菜单id查询该菜单下能后显示的列。 后端返回的数据类型: 接收到后端返回的数据后处理数据结构. Table组件文件 <!-- 自己封装的Table组件文件 --> onMounted(()>…

力扣HOT100之多维动态规划:1143. 最长公共子序列

这道题之前刷代码随想录的时候做过&#xff0c;但是现在又给忘干净了&#xff0c;这道题需要用二维dp数组来做&#xff0c;看了一下自己当时写的博客&#xff0c;一下子就看懂了。这道题的子序列可以不连续&#xff0c;所以dp数组的定义和最长重复子数组不一样&#xff0c;我总…

无锁队列—C++内存序最佳实践

叙述方式&#xff1a; 1.背景介绍 &#xff08;使用场景&#xff09; 2.讲结论 (无锁队列实现) 3.讲内存序的使用&#xff08;通用方式&#xff09; 一、背景 本文通过一个“单生产者-单消费者”模型的场景&#xff0c;讲解基于C原子操作和内存序实现的无锁队列 在生产者…

ADC模数转换控制

目录 1. Convst信号的功能本质 1.1 核心作用 1.2 关键优势 1.3 Convst与SPI接口的协作关系 2.实际设计要点 2.1 硬件连接方案 2.2 时序约束&#xff08;以AD7685为例&#xff09; 2.3 多片ADC同步策略 3.高级应用技巧 3.1 动态调整采样率 3.2 抗干扰设计 3.3 故障排查 4.总…

QT常用控件(1)

控件是构成QT的基础元素&#xff0c;例如Qwidget也是一个控件&#xff0c;提供了一个‘空’的矩形&#xff0c;我们可以往里面添加内容和处理用户输入&#xff0c;例如&#xff1a;按钮&#xff08;QpushButton&#xff09;&#xff0c;基础显示控件&#xff08;Lable&#xff…

Linux系统-基本指令(5)

文章目录 mv 指令cat 指令&#xff08;查看小文件&#xff09;知识点&#xff08;简单阐述日志&#xff09;more 和 less 指令&#xff08;查看大文件&#xff09;head 和 tail 指令&#xff08;跟查看文件有关&#xff09;知识点&#xff08;管道&#xff09;时间相关的指令&a…