基于Qt实现的自定义树结构容器:设计与应用
在Qt框架中,尽管其提供了许多强大的容器类(如 QList
, QMap
, QTreeWidget
等),但缺少一个通用的、灵活的树结构容器,直接支持多层级数据管理。为了满足这些需求,本文设计并实现了一个可复用的自定义树结构容器,并讨论其在不同项目中的应用。
1. 背景与动机
树结构在软件开发中是常见的数据组织形式,常用于以下场景:
- 多层级文件管理器:文件夹与文件的树形展示。
- 层次化关系管理:如公司组织结构、任务依赖关系。
- 数据处理与分类:如属性分类、规则树等。
然而,Qt 中缺少直接的树结构容器(QTreeWidget
是 UI 组件,QAbstractItemModel
偏向于数据视图)。因此,我们实现了一个灵活、可扩展的 通用树结构容器,支持:
- 动态添加和删除节点。
- 为节点附加数据。
- 数据筛选与查找。
- 清晰的树形结构打印与调试。
2. 核心设计与实现
2.1 类设计概览
该树容器包含两个核心类:
-
TreeNode:
- 表示树的单个节点。
- 包括节点名称、父节点指针、子节点列表、节点数据。
- 支持节点添加、删除、数据设置与清除等基本操作。
-
Tree:
- 管理整个树的逻辑。
- 提供全局的节点操作接口,如添加、删除节点,筛选节点数据,打印树结构等。
2.2 TreeNode 类实现
TreeNode 是树结构的核心,负责管理节点的层次关系和数据存储。以下是其关键代码逻辑:
class TreeNode {
public:explicit TreeNode(const QString& name, TreeNode* parent = nullptr);~TreeNode();// 添加子节点TreeNode* addChild(const QString& name);// 移除子节点bool removeChild(TreeNode* child);// 设置与清除节点数据void setData(const QVariant& data);void clearData();// 获取节点信息QVariant getData() const;const QList<TreeNode*>& getChildren() const;QString getName() const;TreeNode* getParent() const;
};
主要功能:
addChild
和removeChild
实现树的动态结构调整。setData
和clearData
支持灵活的节点数据管理。- 提供对父子关系和数据的访问接口。
2.3 Tree 类实现
Tree 是一个树容器的管理类。其设计目标是:
- 提供用户友好的接口,隐藏树节点的内部操作。
- 支持全局的增删改查功能。
以下是 Tree
类的部分接口说明:
class Tree {
public:Tree();~Tree();// 节点操作TreeNode* addNode(TreeNode* parent, const QString& name);bool removeNode(TreeNode* node);// 数据操作void setNodeData(TreeNode* node, const QVariant& data);QVariant getNodeData(TreeNode* node) const;void clearNodeData(TreeNode* node);// 数据筛选与树形打印QList<TreeNode*> filterNodes(const QString& keyword) const;void printTree() const;
};
主要功能:
addNode
:动态添加节点,支持将节点默认添加到根节点。filterNodes
:通过关键字查找包含特定数据的节点。printTree
:以层级缩进格式打印树的结构,便于调试。
2.4 调用示例
以下是使用 Tree
和 TreeNode
的示例代码:
int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);// 创建树容器Tree tree;// 添加节点TreeNode* root = tree.addNode(nullptr, tc("根节点"));TreeNode* nodeA = tree.addNode(root, tc("节点A"));TreeNode* nodeB = tree.addNode(root, tc("节点B"));TreeNode* nodeC = tree.addNode(nodeA, tc("节点C"));// 设置节点数据tree.setNodeData(nodeA, tc("温度过高"));tree.setNodeData(nodeB, tc("正常"));tree.setNodeData(nodeC, tc("压力过低"));// 打印树结构tree.printTree();// 筛选包含 "温度" 的节点QList<TreeNode*> filteredNodes = tree.filterNodes(tc("温度"));qDebug() << tc("筛选结果:");for (TreeNode* node : filteredNodes) {qDebug() << node->getName() << ":" << node->getData().toString();}return a.exec();
}
运行结果:
根节点 ()节点A (温度过高)节点C (压力过低)节点B (正常)筛选结果:
"节点A" : "温度过高"
3. 适用场景分析
该树容器的灵活性使其适用于多种场景,包括但不限于以下项目:
-
文件管理器:
- 以层次结构管理文件夹和文件。
- 节点数据可存储文件的元信息(如路径、大小)。
-
组织结构管理:
- 用于显示公司组织架构(如部门、员工)。
- 节点数据可附加员工信息。
-
规则引擎或决策树:
- 用于实现条件匹配规则。
- 节点存储规则条件与结果。
-
动态数据分类:
- 实现类似标签分类的功能。
- 支持实时增删节点。
-
调试工具:
- 用于显示复杂系统中的内部数据关系。
4. 优势与改进方向
4.1 优势
-
简单易用:
- 接口友好,隐藏复杂的内部操作。
- 提供清晰的错误提示和默认行为。
-
高扩展性:
- 可以轻松添加新功能,如节点排序、自定义过滤条件等。
-
灵活性:
- 节点的数据类型为
QVariant
,支持多种数据类型存储。
- 节点的数据类型为
-
跨平台支持:
- 依赖 Qt 框架,具备良好的跨平台能力。
4.2 改进方向
-
线程安全:
- 增加对并发操作的支持,例如通过
QMutex
实现线程同步。
- 增加对并发操作的支持,例如通过
-
持久化:
- 增加树结构的序列化和反序列化功能,用于存储和加载数据。
-
性能优化:
- 对大规模树操作(如深度遍历)进行优化。
-
模型绑定:
- 将树容器与
QAbstractItemModel
绑定,支持直接用于 Qt 的视图类(如QTreeView
)。
- 将树容器与
5. 结语
本文介绍了一个基于 Qt 实现的自定义树结构容器,其功能涵盖了节点管理、数据存储、筛选与打印等操作,适用于多种项目场景。通过该容器,开发者可以更加灵活地管理复杂的层次化数据,同时其清晰的接口设计也便于扩展与维护。
6. 源码
以下是修正后的完整代码实现,包含 TreeNode.h
、TreeNode.cpp
、Tree.h
、Tree.cpp
和 main.cpp
文件。代码修复了根节点初始化问题,并增强了错误处理和默认逻辑。
TreeNode.h
#ifndef TREENODE_H
#define TREENODE_H#include <QString>
#include <QList>
#include <QVariant>#define tc(a) QString::fromLocal8Bit(a)class TreeNode {
public:explicit TreeNode(const QString& name, TreeNode* parent = nullptr);~TreeNode();// 添加子节点TreeNode* addChild(const QString& name);// 移除子节点bool removeChild(TreeNode* child);// 设置节点数据void setData(const QVariant& data);// 获取节点数据QVariant getData() const;// 移除节点数据void clearData();// 获取所有子节点const QList<TreeNode*>& getChildren() const;// 获取节点名称QString getName() const;// 获取父节点TreeNode* getParent() const;// 检查是否为叶子节点bool isLeaf() const;private:QString nodeName; // 节点名称QVariant nodeData; // 节点数据TreeNode* parentNode; // 父节点QList<TreeNode*> childNodes; // 子节点列表
};#endif // TREENODE_H
TreeNode.cpp
#include "TreeNode.h"
#include <QDebug>TreeNode::TreeNode(const QString& name, TreeNode* parent): nodeName(name), parentNode(parent) {}TreeNode::~TreeNode() {qDeleteAll(childNodes); // 删除所有子节点
}TreeNode* TreeNode::addChild(const QString& name) {TreeNode* child = new TreeNode(name, this);childNodes.append(child);return child;
}bool TreeNode::removeChild(TreeNode* child) {if (!child || !childNodes.contains(child)) {qWarning() << tc("移除失败:节点不存在!");return false;}childNodes.removeAll(child);delete child; // 删除子节点及其数据return true;
}void TreeNode::setData(const QVariant& data) {nodeData = data;
}QVariant TreeNode::getData() const {return nodeData;
}void TreeNode::clearData() {nodeData.clear();
}const QList<TreeNode*>& TreeNode::getChildren() const {return childNodes;
}QString TreeNode::getName() const {return nodeName;
}TreeNode* TreeNode::getParent() const {return parentNode;
}bool TreeNode::isLeaf() const {return childNodes.isEmpty();
}
Tree.h
#ifndef TREE_H
#define TREE_H#include "TreeNode.h"class Tree {
public:Tree();~Tree();// 添加节点TreeNode* addNode(TreeNode* parent, const QString& name);// 移除节点bool removeNode(TreeNode* node);// 设置节点数据void setNodeData(TreeNode* node, const QVariant& data);// 获取节点数据QVariant getNodeData(TreeNode* node) const;// 移除节点数据void clearNodeData(TreeNode* node);// 查找节点(通过名称)TreeNode* findNode(TreeNode* root, const QString& name) const;// 过滤节点(通过数据关键字)QList<TreeNode*> filterNodes(const QString& keyword) const;// 打印树结构void printTree() const;private:TreeNode* root;// 辅助递归方法void filterRecursive(TreeNode* node, const QString& keyword, QList<TreeNode*>& result) const;void printRecursive(TreeNode* node, int depth) const;
};#endif // TREE_H
Tree.cpp
#include "Tree.h"
#include <QDebug>Tree::Tree() {root = new TreeNode(tc("根节点"));qDebug() << tc("成功初始化根节点。");
}Tree::~Tree() {delete root; // 自动删除所有节点
}TreeNode* Tree::addNode(TreeNode* parent, const QString& name) {if (!parent) {if (!root) {qWarning() << tc("添加失败:根节点未创建!");return nullptr;}qDebug() << tc("未指定父节点,默认添加到根节点。");parent = root; // 如果父节点为空,默认添加到根节点}return parent->addChild(name);
}bool Tree::removeNode(TreeNode* node) {if (!node || node == root) {qWarning() << tc("移除失败:节点为空或为根节点!");return false;}TreeNode* parent = node->getParent();if (!parent) {qWarning() << tc("移除失败:父节点为空!");return false;}return parent->removeChild(node);
}void Tree::setNodeData(TreeNode* node, const QVariant& data) {if (!node) {qWarning() << tc("设置失败:节点为空!");return;}node->setData(data);
}QVariant Tree::getNodeData(TreeNode* node) const {if (!node) {qWarning() << tc("获取失败:节点为空!");return QVariant();}return node->getData();
}void Tree::clearNodeData(TreeNode* node) {if (!node) {qWarning() << tc("清除失败:节点为空!");return;}node->clearData();
}TreeNode* Tree::findNode(TreeNode* root, const QString& name) const {if (!root) return nullptr;if (root->getName() == name) return root;for (TreeNode* child : root->getChildren()) {TreeNode* found = findNode(child, name);if (found) return found;}return nullptr;
}QList<TreeNode*> Tree::filterNodes(const QString& keyword) const {QList<TreeNode*> result;filterRecursive(root, keyword, result);return result;
}void Tree::filterRecursive(TreeNode* node, const QString& keyword, QList<TreeNode*>& result) const {if (node->getData().toString().contains(keyword)) {result.append(node);}for (TreeNode* child : node->getChildren()) {filterRecursive(child, keyword, result);}
}void Tree::printTree() const {printRecursive(root, 0);
}void Tree::printRecursive(TreeNode* node, int depth) const {qDebug().noquote() << QString(depth * 2, ' ') + node->getName() + " (" + node->getData().toString() + ")";for (TreeNode* child : node->getChildren()) {printRecursive(child, depth + 1);}
}
main.cpp
#include <QCoreApplication>
#include "Tree.h"int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);// 创建树Tree tree;// 创建子节点,明确传入父节点TreeNode* nodeA = tree.addNode(nullptr, tc("节点A")); // 默认添加到根节点TreeNode* nodeB = tree.addNode(nodeA, tc("节点B"));TreeNode* nodeC = tree.addNode(nodeA, tc("节点C"));// 添加数据tree.setNodeData(nodeA, tc("温度过高"));tree.setNodeData(nodeB, tc("正常"));tree.setNodeData(nodeC, tc("压力过低"));// 获取数据qDebug() << tc("节点A数据:") << tree.getNodeData(nodeA).toString();// 清除数据tree.clearNodeData(nodeC);// 过滤节点QList<TreeNode*> filteredNodes = tree.filterNodes(tc("温度"));qDebug() << tc("过滤结果:");for (TreeNode* node : filteredNodes) {qDebug() << node->getName() << ":" << node->getData().toString();}// 打印树结构tree.printTree();return a.exec();
}
运行结果
成功初始化根节点。
未指定父节点,默认添加到根节点。
未指定父节点,默认添加到根节点。
未指定父节点,默认添加到根节点。
节点A数据: "温度过高"
过滤结果:
"节点A" : "温度过高"
根节点 ()节点A (温度过高)节点B (正常)节点C ()
功能总结
该实现支持树节点的 添加、删除、查询、过滤,以及节点数据的 设置、获取、清除。同时,包含中文提示与日志输出,逻辑健壮且易于扩展。
相关文章:
基于Qt实现的自定义树结构容器:设计与应用
在Qt框架中,尽管其提供了许多强大的容器类(如 QList, QMap, QTreeWidget 等),但缺少一个通用的、灵活的树结构容器,直接支持多层级数据管理。为了满足这些需求,本文设计并实现了一个可复用的自定义树结构容…...
Minio 客户端 mc
1、文档参阅: 1.1、 服务别名设置: https://min.io/docs/minio/linux/reference/minio-mc/mc-alias-set.html 1.2、cp 命令 https://min.io/docs/minio/linux/reference/minio-mc/mc-cp.html 2、mc 命令安装 1、wget https://dl.minio.org.cn/cl…...
python控制鼠标,键盘,adb
python控制鼠标,键盘,adb 听说某系因为奖学金互相举报,好像拿不到要命一样。不禁想到几天前老墨偷走丁胖子的狗,被丁胖子逮到。他面对警察的问询面不改色坚持自我,反而是怒气冲冲的丁胖子被警察认为是偷狗贼。我觉得这…...
使用 Python 剪辑视频的播放速度
要使用 Python 调整视频的播放速度,可以利用 moviepy 库中的 fx(特效)模块来实现这一功能。通过 moviepy.editor 中的 VideoFileClip 类和 fx.speedx 函数,可以轻松地调整视频的播放速度。 安装 moviepy 首先,确保已…...
Scrapy图解工作流程-cnblog
1.1 介绍部分: 文字提到常用的Web框架有Django和Flask,接下来将学习一个全球范围内流行的爬虫框架Scrapy。 1.2 内容部分: Scrapy的概念、作用和工作流程 Scrapy的入门使用 Scrapy构造并发送请求 Scrapy模拟登陆 Scrapy管道的使用 Scrapy中…...
mongodb
MongoDB增加身份验证 - jason47 - 博客园 db.collection.find() - MongoDB 手册 v6.0 1. 登录 rootJTVMbushu104:~# mongosh # 无账号登录 test> use admin # 切换数据库,先切换到有权限数据库再登录授权 switched to db admin admin> db.auth(username,pas…...
海量数据处理面试题
目录 一.位图应用 二.布隆过滤器 三.哈希切割 一.位图应用 1. 给定100亿个整数,设计算法找到只出现一次的整数? 对于这道题100亿个整数大概占用40G,1G2^30byte,所以直接保存是不合适的,可以使用两个位图来处理,用00表示出现0次的,01表示出现一次的,10…...
RNN模型文本预处理--数据增强方法
数据增强方法 数据增强是自然语言处理(NLP)中常用的一种技术,通过生成新的训练样本来扩充数据集,从而提高模型的泛化能力和性能。回译数据增强法是一种常见的数据增强方法,特别适用于文本数据。 回译数据增强法 定义…...
git-显示顺序与提交顺序不一致的问题
问题流程 a分支 初始记录:分支的提交记录是 c1 -> c2 -> c3第一次修改提交记录但并未push:a1(20:18)第二次修改提交记录:a2(20:20) b分支 初始记录: c1 -> c2 -> c3 …...
【软件入门】Git快速入门
Git快速入门 文章目录 Git快速入门0.前言1.安装和配置2.新建版本库2.1.本地创建2.2.云端下载 3.版本管理3.1.添加和提交文件3.2.回退版本3.2.1.soft模式3.2.2.mixed模式3.2.3.hard模式3.2.4.使用场景 3.3.查看版本差异3.4.忽略文件 4.云端配置4.1.Github4.1.1.SSH配置4.1.2.关联…...
基于Springboot的流浪宠物管理系统
基于javaweb的流浪宠物管理系统 介绍 基于javaweb的流浪宠物管理系统的设计与实现,后端框架使用Springbootmybatis,前端框架使用Vuehrml,数据库使用mysql,使用B/S架构实现前台用户系统和后台管理员系统,和不同权限级别…...
【踩坑日记】【教程】如何在ubuntu服务器上配置公钥登录以及bug解决
前言 在日常开发和运维中,为了提高服务器登录的安全性,我们通常会选择使用 SSH 密钥认证 来替代传统的密码登录。然而,在配置 SSH 公钥登录的过程中,可能会遇到各种坑和 Bug。本文将从零开始,手把手教你如何在 Ubuntu…...
使用 VLC 在本地搭建流媒体服务器 (详细版)
提示:详细流程 避坑指南 Hi~!欢迎来到碧波空间,平时喜欢用博客记录学习的点滴,欢迎大家前来指正,欢迎欢迎~~ ✨✨ 主页:碧波 📚 📚 专栏:音视频 目录 借助VLC media pl…...
常用贴片元件封装尺寸
不论你在什么时候开始,重要的是开始之后就不要停止。 一天过完,不会再来。 每一次发奋努力的背后,必有加倍的赏赐。【SMD贴片元件的封装尺寸】 公制:3216——2012——1608——1005——0603——0402 英制:1206——0805—…...
NVR录像机汇聚管理EasyNVR多个NVR同时管理基于B/S架构的技术特点与能力应用
EasyNVR视频融合平台基于云边端协同设计,能够轻松接入并管理海量的视频数据。该平台兼容性强、拓展灵活,提供了视频监控直播、录像存储、云存储服务、回放检索以及平台级联等一系列功能。B/S架构使得EasyNVR实现了视频监控的多元化兼容与高效管理。 其采…...
【时间之外】IT人求职和创业应知【48】-通信技术
目录 新闻一:腾讯科技取得数据显示相关专利 新闻二:中国5G网络规模全球最大,6G技术取得突破 新闻三:亚马逊启动“登月”计划,部署10万颗二代自研芯片 连亚马逊这样的大厂也搞登月计划,可见现在的业界竞争…...
如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间
如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间 一、前言二、准备工作三、扩展逻辑卷1. 检查现有 LVM 配置2. 扩展物理卷3. 扩展卷组4. 扩展逻辑卷四、调整文件系统大小1. 检查文件系统状态2. 扩展文件系统五、处理可能出现的问题1. 文件系统无法扩展2. 磁盘空间不足3…...
Linux命令操作基础
目录 一、命令格式 二、常见命令操作 2.1补齐命令与文件名 2.2历史命令 2.3联机帮助 三、常用命令 四、vim/vi文本编辑器 4.1命令模式 4.2输出模式 4.3底线命令模式 一、命令格式 $ Command [-Options] Argument1 Argument2... 其中: $:默认存在的提示符&a…...
Shell脚本实践练习
声明 学习视频来自 B 站UP主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 ✍🏻作者简介:致…...
CentOS上如何离线批量自动化部署zabbix 7.0版本客户端
CentOS上如何离线批量自动化部署zabbix 7.0版本客户端 管理的服务器大部分都是CentOS操作系统,版本主要是CentOS 7。因为监控服务器需要,要在前两天搭建的Zabbix 7.0系统上把这些CentOS 7系统都监控起来。因为服务器数量众多,而且有些服务器…...
DDR3与MIG IP核详解(一)
一、ddr3(全称第三代双倍速率同步动态随机存储器): 1、特点:1:掉电无法保存数据,需要周期性的刷新。2:时钟上升沿和下降沿都会传输数据。 3:突发传输,突发长度 Burst Length一般为…...
转录组数据挖掘(生物技能树)(第11节)下游分析
转录组数据挖掘(生物技能树)(第11节) 文章目录 R语言复习转录组数据差异分析差异分析的输入数据操作过程示例一:示例二:示例三:此代码只适用于人的样本 R语言复习 #### 读取 ####dat read.deli…...
CTF-RE 从0到N:Chacha20逆向实战 2024 强网杯青少年专项赛 EnterGame WP (END)
只想解题的看最后就好了,前面是算法分析 Chacha20 c语言是如何利用逻辑运算符拆分变量和合并的 通过百度网盘分享的文件:EnterGame_9acdc7c33f85832082adc6a4e... 链接:https://pan.baidu.com/s/182SRj2Xemo63PCoaLNUsRQ?pwd1111 提取码:1…...
Spring Boot 的 WebClient 实践教程
什么是 WebClient? 在 Spring Boot 中,WebClient 是 Spring WebFlux 提供的一个非阻塞、响应式的 HTTP 客户端,用于与 RESTful 服务或其他 HTTP 服务交互。相比于传统的 RestTemplate,WebClient 更加现代化,具有异步和…...
STM32笔记(串口IAP升级)
一、IAP简介 IAP(In Application Programming)即在应用编程, IAP 是用户自己的程序在运行过程中对 User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产 品中的固件程序进行更新升级。 通常实…...
Ollama - 简化使用本地大语言模型
学习完用 Transformers 和 llama.cpp 使用本地大语言模型后,再继续探索如何使用 Ollama 跑模型。Ollama 让运行和管理大语言模型变得更为简单,它构建在 llama.cpp 之上,并有优化,性能表现同样不俗。下面罗列一下它的特点 从它的 …...
圆域函数的傅里叶变换和傅里叶逆变换
空域圆域函数的傅里叶变换 空域圆域函数(也称为空间中的圆形区域函数)通常指的是在二维空间中,以原点为中心、半径为 a a a的圆内取值为1,圆外取值为0的函数。这种函数可以表示为: f ( x , y ) { 1 if x 2 y 2 ≤ …...
智能交易模型的全景探索:量化技术的进步与未来
随着金融市场日益复杂化,量化交易模型在投资领域扮演着愈加重要的角色。这些模型通过数据驱动和技术创新,赋能投资者在高度波动的市场中寻找确定性收益点。本文将从技术进步、模型构建、应用优势和未来发展四个方面,探讨量化交易模型的演变与…...
mysql学习
1、 数据库的三范式是什么? 2、特点 - 永久性:从本质上来说数据库中的数据以计算机文件的方式存储在磁盘上- 结构性:数据不是杂乱无章的存储- 大量:只受到磁盘空间的影响 3、 Myisam与innodb的区别 4、mysql架构 开始编程语言进…...
小白新手村冒险之“烤”json串
JSON是什么? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,但是JSON是独立于语言的文本格式,许多编…...
SQL基础入门—— 简单查询与条件筛选
在SQL中,查询是从数据库中获取数据的核心操作,而条件筛选是查询中不可或缺的一部分。通过使用条件筛选,我们可以精准地从大量数据中提取我们需要的信息。本节将详细讲解如何使用SQL进行简单查询与条件筛选,包含常见的条件运算符和…...
Java线程池种类及具体应用场景
Java线程池种类及具体应用场景 在实际开发中,选择合适的线程池类型至关重要,不同场景有不同的线程池需求。本文将结合线程池种类和具体应用示例,详细说明每种线程池的使用场景和适用情况。 一、固定大小线程池(FixedThreadPool&a…...
3D建筑模型的 LOD 规范
LOD(细节层次) 是3D城市建模中用于表示建筑模型精细程度的标准化描述不同的LOD适用于不同的应用场景 LOD是3D建模中重要的分级标准,不同层级适合不同精度和用途的需求。 从LOD0到LOD4,细节逐渐丰富,复杂性和精度也逐…...
掌上单片机实验室 — RT - Thread+ROS2 浅尝(26)
前面化解了Micro_ROS通讯问题,并在 RT-Thread Studio 环境下,使用Micro_ROS软件包中的例程,实现了STM32F411CE核心板和ROS2主机的通讯。之后还尝试修改例程 micro_ros_sub_twist.c ,实现了接收 turtle_teleop_key 所发出的 turtle…...
同步时序电路——描述
这部分要求了解一些触发器的状态方程: R-S触发器: D触发器: JK触发器: 时序电路:任一时刻的输出既与即刻输入有关(若有输入),还与电路当时的状态有关(和以前的输入有关),即电路具有记忆能力。 时…...
.net的winfrom程序 窗体透明打开窗体时出现在屏幕右上角
窗体透明, 将Form的属性Opacity,由默认的100% 调整到 80%,这个数字越小越透明(尽量别低于50%,不信你试试看)! 打开窗体时出现在屏幕右上角 //构造函数 public frmCalendarList() {InitializeComponent();//打开窗体&…...
反爬虫机制
许多网站会采取措施来防止爬虫频繁访问或抓取大量内容,这些措施被称为反爬虫机制。常见的反爬手段包括: IP 限制:通过检测频繁访问的 IP 地址,限制该 IP 的访问。 请求频率限制:网站可能通过检测请求间隔过短来判断是…...
ML 系列:第 31 节— 机器学习中的协方差和相关性
文章目录 一、说明二、协方差和相关性2.1 协方差的概念2.1 相关 三、有关关联的高级主题 (有关详细信息)3.1 相关性和独立性3.2 零相关性和依赖性示例 四、相关性和因果关系五、结论 一、说明 协方差量化了两个随机变量协同变化的程度。当一个变量的较高…...
registry 删除私有仓库镜像
原文链接:https://blog.csdn.net/yogima/article/details/122172744 如果需要彻底删除,只需进行register 磁盘删除镜像 彻底删除了,就可以到达彻底删除的目的。 如果只需要软删除,则只需进行通过API删除。 curl --header "Ac…...
初识java(3)
大家好,今天我们来讲讲我们的老伙计-变量,在哪一门编程语言中,变量的作用都是不可或缺的,那么下面我们就来详细了解一下java中的变量。 一.变量概念 在程序中,除了有始终不变的常量外,有些内容可能会经常…...
前端JavaScript(一)---基本介绍
Javascript是一种由Netscape(网景)的LiveScript发展而来的原型化继承的面向对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如Perl,遗留的速度问题,为客户提供更流畅的浏览效果。当时服务端需要对…...
【Linux打怪升级记 | 报错02】-bash: 警告:setlocale: LC_TIME: 无法改变区域选项 (zh_CN.UTF-8)
🗺️博客地图 📍1、报错发现 📍2、原因分析 📍3、解决办法 📍4、测试结果 1、报错发现 装好了CentOS操作系统,使用ssh远程登陆CentOS,出现如下告警信息: bash: 警告:setlocale…...
P1198 [JSOI2008] 最大数
P1198 [JSOI2008] 最大数https://www.luogu.com.cn/problem/P1198 牵制芝士:单调队列 思路: 我们的任务是找出一个区间最大值的 因为插入的数与上一次的答案有关 所以它是强制在线的(真无语了) 我们可以在每次插入时整一个叫…...
嵌入式串口通信 基于芯片STC8H8K64U 串口通信入门001
引言 差不多有四年的时间没有写csdn的原创文章了。一方面是由于家庭的角色转换,已为人母,家中的很多琐事牵绊了我。另一方面是因为工作确实也非常的忙碌。工作需要,也会不断地学习新的知识和复习旧的知识,思来想去,还是决心把工作中的经验心得和遇到的问题,和各位程序猿朋…...
基于Java的小程序电商商城开源设计源码
近年来电商模式的发展越来越成熟,基于 Java 开发的小程序电商商城开源源码,为众多开发者和企业提供了构建个性化电商平台的有力工具。 基于Java的电子商城购物平台小程序的设计在手机上运行,可以实现管理员;首页、个人中心、用户…...
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker pull线上镜像方式构建编译环境
T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求: 硬件: 设备容量备注硬盘>500G多版本系统测试,必须固态,否则编译卡死硬盘>300G单系统…...
计算机网络八股整理(二)
计算机网络八股整理(二) 应用层 1:dns的全称了解过吗? dns全称domain-name-system,翻译过来就是域名系统,是在计算机网络中将域名转换成ip地址的分布式数据库系统; 域名服务器的层级类似一个树…...
华财术_号卡分销平台讲解(四大运营商+手机卡)
【号卡分销平台对比讲解稿】 大家好,今天我们来详细对比几款热门的号卡分销平台,帮助您找到最适合自己的合作伙伴。我们将从佣金结算、数据安全、功能特性、用户体验以及适用人群等多个维度进行剖析,让您一目了然各平台的优劣。 一、号易号…...
fatal error in include chain (rtthread.h):rtconfig.h file not found
项目搜索这个文件 rtconfig 找到后将其复制粘贴到 你的目录\Keil\ARM\ARMCC\include 应该还有cJSON,rtthread.h和 等也复制粘贴下...
服务器记录所有用户docker操作,监控删除容器/镜像的人
文章目录 使用场景安装auditd添加docker审计规则设置监控日志大小与定期清除查询 Docker 操作日志查看所有用户,所有操作日志查看特定用户的 Docker 操作查看所有用户删除容器/镜像日志过滤特定时间范围内日志 使用场景 多人使用的服务器,使用的docker …...