osg实现鼠标框选

目录

1. 需求的提出

2. 具体实现

     2.1. 禁止场景跟随鼠标转动

     2.2. 矩形框前置绘制

3. 附加说明

        3.1. 颜色设置说明

        3.2.矩形框显示和隐藏的另一种实现


1. 需求的提出

       有时需要在屏幕通过按住键盘上的某个键如Ctrl键且按住鼠标左键,拖出一个矩形,实现框选三维物体,如下效果:

现在的问题是:

  1. 在osg中,拖动鼠标时,物体会随鼠标一起转动,这样框选是不行的,至少是不友好的,我们需要的是,按住鼠标框选时,物体不能随鼠标一起转动。
  2. 如何根据鼠标拖动的起始点和终止点,绘制出这个矩形框?矩形框要在所有三维物体的前面而不能被三维物体遮挡且要是透明的,能透过它看到背后的三维物体,否则框选就失去了意义。
  3. 按住鼠标右键,矩形框消失。

2. 具体实现

     2.1. 禁止场景跟随鼠标转动

        对第1节中提到的第1个问题,默认情况下osgViewer::Viewer事件处理器在鼠标左键按下并拖动时,整个场景会随鼠标一起转动。为了不让转动,可以通过改写osgViewer::Viewer osgGA::GUIEventHandler事件处理器,重载如下方法:

 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor*nv)

当按住键盘上的某个键如Ctrl键且按住鼠标左键,让该函数返回true,这样后续的流程就不会处理鼠标拖动事件,三维物体也就不会跟随鼠标旋转了。

     2.2. 矩形框前置绘制

         矩形框要绘制在所有三维物体的前面而不能被三维物体遮挡,这就要用到三维中的HUD技术(Head Up Display)。所谓HUD节点,说白了就是无论三维场景中的内容怎么改变,它都能在屏幕上固定位置显示的节点。实现要点:

  • 关闭光照,不受场景光照影响,所有内容以同一亮度显示。
  • 关闭深度测试。
  • 调整渲染顺序,使它的内容最后绘制。
  • 设定参考贴为绝对型:setReferenceFrame(osg::Transform:ABSOLUTE_RF)。
  • 使其不受父节点变换的影响:setMatrix(osg::Matrix::identity())。
  • 使用平行投影,设定虚拟投影窗口的大小,这个窗口的大小决定了后面绘制的图形和文字的尺度比例。

  实现代码如下:

#include<osgViewer/Viewer>
#include<osg/ShapeDrawable>
#include<osgDB/readFile>
#include<osg/BlendFunc>
class selectBoxEventHandler: public osgGA::GUIEventHandler
{
public:selectBoxEventHandler(osg::ref_ptr<osg::Camera> spHudCamera){m_spHudCamera = spHudCamera;}
private:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor*nv){m_pViewer = (osgViewer::Viewer*)(&aa);if (m_pViewer == nullptr){return false;}auto width = m_pViewer->getCamera()->getViewport()->width();auto height = m_pViewer->getCamera()->getViewport()->height();/* 设置HUD相机为正投影,这样绘制的矩形框和鼠标拖动的框选框大小就一样了且要设置正投影的区域和视图窗体一样大小,因为鼠标可以在窗体任何位置进行框选*/m_spHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));auto eventType = ea.getEventType();switch (eventType){case osgGA::GUIEventAdapter::KEYDOWN:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey()) || (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = true;}}break;case osgGA::GUIEventAdapter::KEYUP:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被释放{m_ctrlKeyPressed = false;}}break;case osgGA::GUIEventAdapter::PUSH:  // 鼠标左键按下{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn){m_fStartPosX = ea.getX();m_fStartPosY = ea.getY();m_bPush = true;}else if (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // 鼠标右键按下,则删除选择框{if (m_spOldNode != nullptr){m_spHudCamera->removeChild(m_spOldNode);}}}break;case osgGA::GUIEventAdapter::RELEASE:  // 释放鼠标左键{m_bPush = false;}break;case osgGA::GUIEventAdapter::DRAG:    // 拖动鼠标{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn && m_ctrlKeyPressed && m_bPush){m_fEndPosX = ea.getX();m_fEndPosY = ea.getY();auto pSelectBox = createSelectBox(m_fStartPosX, m_fStartPosY, m_fEndPosX, m_fEndPosY);if (m_spOldNode != nullptr){m_spHudCamera->removeChild(m_spOldNode);}m_spHudCamera->addChild(pSelectBox);m_spOldNode = pSelectBox;return true;}}} // end swithreturn  false;}osg::Geode* createSelectBox(float fStartPosX, float fStartPosY, float fEndPosX, float fEndPosY){osg::Geode* pGeode = new osg::Geode();auto pQuardGeomerty = new osg::Geometry();pGeode->addChild(pQuardGeomerty);osg::Vec3Array* pVertArray = new osg::Vec3Array;pVertArray->push_back(osg::Vec3(fStartPosX, fStartPosY, 0.0));pVertArray->push_back(osg::Vec3(fStartPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fStartPosY, 0.0));pQuardGeomerty->setVertexArray(pVertArray);osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));/*  pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));*/pQuardGeomerty->setColorArray(pColorArray);//pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_PRIMITIVE_SET);pQuardGeomerty->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 关闭光照pGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); // 开启透明,否则就不能透过选择框看到后面的牛pGeode->addDrawable(pQuardGeomerty);return pGeode;}private:/* 鼠标按下的起始坐标点 */float m_fStartPosX{0.0};float m_fStartPosY{ 0.0 };float m_fEndPosX{ 0.0 };float m_fEndPosY{ 0.0 };bool m_ctrlKeyPressed{false};             // Ctrl键被按下bool m_bPush{false};                      // 鼠标左键是否被按下osgViewer::Viewer* m_pViewer{nullptr};osg::ref_ptr<osg::Camera> m_spHudCamera;  // 用于HUD的相机osg::ref_ptr<osg::Node> m_spOldNode;      // 上次鼠标框选绘制出的矩形框};
int main(int argc, char *argv[])
{osgViewer::Viewer viewer;auto cowNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\cow.osg)");if (nullptr == cowNode){OSG_WARN << "node is null!";return 1;}auto spRoot = new osg::Group();osg::ref_ptr<osg::Camera> spHudCamera = new osg::Camera;spHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);  // 关闭深度缓冲// 设置渲染顺序为后渲染,即始终在其它绘制物体的上面,防止被其它绘制的物体遮挡spHudCamera->setRenderOrder(osg::Camera::RenderOrder::POST_RENDER); spHudCamera->setAllowEventFocus(false);  // 不接受任何焦点事件,即不响应键盘、鼠标事件spHudCamera->setReferenceFrame(osg::Transform::ReferenceFrame::ABSOLUTE_RF); // 设置参考帧为绝对帧spHudCamera->setViewMatrix(osg::Matrix::identity()); // 设置相机视图矩阵为单位矩阵,这样就矩形框选框就不受相机旋转等变换影响spRoot->addChild(cowNode);spRoot->addChild(spHudCamera);viewer.setSceneData(spRoot);viewer.addEventHandler(new selectBoxEventHandler(spHudCamera));return viewer.run();
}

3. 附加说明

        3.1. 颜色设置说明

              2.2节代码对颜色的设置,也可以按如下代码一样达到同样的效果:

 osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pQuardGeomerty->setColorArray(pColorArray);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);

也就是说设置一个顶点的颜色且颜色绑定方式为BIND_PER_PRIMITIVE_SET和分别设置4个顶点颜色,颜色绑定方式为BIND_PER_VERTEX效果相同。关于BIND_PER_PRIMITIVE_SET和BIND_PER_VERTEX的具体含义和不同点,请参考:osg图元绑定方式总结博文。

        3.2.矩形框显示和隐藏的另一种实现

       上面矩形框的显示和隐藏是通过removeChild和addChild函数来实现的,即将新的矩形框节点加入到相机作为其子节点之前,删除上次创建的矩形框节点。也可以通过osg::Node的setNodeMask函数来实现,如下为更改后的代码:

#include<osgViewer/Viewer>
#include<osg/ShapeDrawable>
#include<osgDB/readFile>
#include<osg/BlendFunc>#define HIDE_SELECT_BOX 0X0
#define  SHOW_SELECT_BOX ~HIDE_SELECT_BOXclass selectBoxEventHandler : public osgGA::GUIEventHandler
{
public:selectBoxEventHandler(osg::ref_ptr<osg::Camera> spHudCamera){m_spHudCamera = spHudCamera;}
private:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv){m_pViewer = (osgViewer::Viewer*)(&aa);if (m_pViewer == nullptr){return false;}auto width = m_pViewer->getCamera()->getViewport()->width();auto height = m_pViewer->getCamera()->getViewport()->height();/* 设置HuD相机为正投影,这样绘制的矩形框和鼠标拖动的框选框大小就一样了且要设置正投影的区域和视图窗体一样大小,因为鼠标可以在窗体任何位置进行框选*/m_spHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));auto eventType = ea.getEventType();switch (eventType){case osgGA::GUIEventAdapter::KEYDOWN:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = true;}}break;case osgGA::GUIEventAdapter::KEYUP:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = false;}}break;case osgGA::GUIEventAdapter::PUSH:  // 鼠标左键按下{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn){m_fStartPosX = ea.getX();m_fStartPosY = ea.getY();m_bPush = true;}else if (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // 鼠标右键按下,则删除选择框{if (m_spRectGeometry != nullptr){m_spRectGeometry->setNodeMask(HIDE_SELECT_BOX);}}}break;case osgGA::GUIEventAdapter::RELEASE:  // 释放鼠标左键{m_bPush = false;}break;case osgGA::GUIEventAdapter::DRAG:    // 拖动鼠标{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn && m_ctrlKeyPressed && m_bPush){m_fEndPosX = ea.getX();m_fEndPosY = ea.getY();if (nullptr != m_spRectGeometry){auto pVertArray = (osg::Vec3Array*)m_spRectGeometry->getVertexArray();(*pVertArray)[0].set(m_fStartPosX, m_fStartPosY, 0.0);(*pVertArray)[1].set(m_fStartPosX, m_fEndPosY, 0.0);(*pVertArray)[2].set(m_fEndPosX, m_fEndPosY, 0.0);(*pVertArray)[3].set(m_fEndPosX, m_fStartPosY, 0.0);// m_spRectGeometry->setVertexArray(pVertArray);m_spRectGeometry->dirtyDisplayList(); // 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形m_spRectGeometry->setNodeMask(SHOW_SELECT_BOX);}else{auto spSelectBox = createSelectBox(m_fStartPosX, m_fStartPosY, m_fEndPosX, m_fEndPosY);m_spRectGeometry = spSelectBox->asGeode()->getChild(0)->asGeometry();m_spHudCamera->addChild(spSelectBox);}return true;}}} // end swithreturn  false;}osg::Geode* createSelectBox(float fStartPosX, float fStartPosY, float fEndPosX, float fEndPosY){osg::Geode* pGeode = new osg::Geode();auto pQuardGeomerty = new osg::Geometry();pGeode->addChild(pQuardGeomerty);osg::Vec3Array* pVertArray = new osg::Vec3Array;pVertArray->push_back(osg::Vec3(fStartPosX, fStartPosY, 0.0));pVertArray->push_back(osg::Vec3(fStartPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fStartPosY, 0.0));pQuardGeomerty->setVertexArray(pVertArray);osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));/*  pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));*/pQuardGeomerty->setColorArray(pColorArray);//pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_PRIMITIVE_SET);pQuardGeomerty->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 关闭光照pGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); // 开启透明,否则就不能透过选择框看到后面的牛pGeode->addDrawable(pQuardGeomerty);return pGeode;}private:/* 鼠标按下的起始坐标点 */float m_fStartPosX{ 0.0 };float m_fStartPosY{ 0.0 };float m_fEndPosX{ 0.0 };float m_fEndPosY{ 0.0 };bool m_ctrlKeyPressed{ false };             // Ctrl键被按下bool m_bPush{ false };                      // 鼠标左键是否被按下osgViewer::Viewer* m_pViewer{ nullptr };osg::ref_ptr<osg::Camera> m_spHudCamera;  // 用于HUD的相机osg::ref_ptr<osg::Geometry> m_spRectGeometry;      // 矩形框};int main(int argc, char *argv[])
{osgViewer::Viewer viewer;auto cowNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\cow.osg)");if (nullptr == cowNode){OSG_WARN << "node is null!";return 1;}auto spRoot = new osg::Group();osg::ref_ptr<osg::Camera> spHudCamera = new osg::Camera;spHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);  // 开启深度缓冲// 设置渲染顺序为后渲染,即始终在其它绘制物体的上面,防止被其它绘制的物体遮挡spHudCamera->setRenderOrder(osg::Camera::RenderOrder::POST_RENDER); spHudCamera->setAllowEventFocus(false);  // 不接受任何焦点事件,即不响应键盘、鼠标事件spHudCamera->setReferenceFrame(osg::Transform::ReferenceFrame::ABSOLUTE_RF); // 设置参考帧为绝对帧spHudCamera->setViewMatrix(osg::Matrix::identity()); // 设置相机视图矩阵为单位矩阵,这样就矩形框选框就不受相机旋转等变换影响spRoot->addChild(cowNode);spRoot->addChild(spHudCamera);viewer.setSceneData(spRoot);viewer.addEventHandler(new selectBoxEventHandler(spHudCamera));return viewer.run();
}

说明

  • 在鼠标拖动坐标改变重新设置矩形框坐标时,记得调用:           
// 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形 
m_spRectGeometry->setVertexArray(pVertArray);

或调用:

 m_spRectGeometry->dirtyDisplayList(); // 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形

在C++中,只要把指针指向的内容改了,也就是立马改了,但在上述代码中如果以为只把顶点数据改了,新矩形就会呈现出来是错误的,不调用上述代码中的某一种,新矩形不会绘制,因为只改了顶点数据,但osg还没执行重绘。

  • 上述采用节点的setNodeMask函数,通过设置节点掩码来实现矩形框的显示或隐藏,其实最好的方法是采用osg::Switch来控制矩形框的显示和隐藏,在此不再详述列出代码,关于这两者的详述,参见:osg利用setNodeMask和Switch隐藏节点用法说明博文。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/94871.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ValueError: check_hostname requires server_hostname

使用jupyter 下载js2py 异常 !pip install js2py ValueError: check_hostname requires server_hostname 一开始以为是数据源问题&#xff0c;切换阿里云 还是这个异常 结果发现是开魔法导致的&#xff0c;关闭魔法即可

怒刷LeetCode的第23天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;贪心算法 方法二&#xff1a;动态规划 方法三&#xff1a;回溯算法 方法四&#xff1a;并查集 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;排序和遍历 方法二&#xff1a;扫描线算法 方法…

英伟达NVIDIA驱动安装

一般&#xff0c;我们新的显卡上机或者新系统可能就需要重新安装显卡驱动。或者是我们在配置深度学习环境时候&#xff0c;需要手动安装驱动。 官网地址&#xff1a;官方高级驱动搜索 | NVIDIA 我们选择好自己需要的驱动后直接安装即可 下载的时候&#xff0c;选择自己需要的驱…

计算机竞赛 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习&#xff1f;5.1.2 为什么要迁移学习&#xff1f; 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…

JavaSE | 初识Java(一) | JDK \ JRE \ JVM

Java初识 Java 是一门半编译型、半解释型语言。先通过 javac 编译程序把源文件进行编译&#xff0c;编译后生成的 .class 文件是由字节 码组成的平台无关、面向 JVM 的文件。最后启动 java 虚拟机 来运行 .class 文件&#xff0c;此时 JVM 会将字节码转换成平台能够理…

线程的概述

#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 功能&#xff1a;创建一个子线程 参数&#xff1a; -thread:传出参数&#xff0c;线程创建成功后&#xff0c;子线程的ID被写到…

日常工作报告生成器微信小程序源码 支持日报,周报,月报,年终终结

相信大家上班都会有做工作报告的情况吧 那么这款小程序就是大家的福音了 只要输入你的工作内容或者岗位自动生成你的工作报告 支持报,周报,月报,年终终结 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88391810 源码下载2&#xff1a;评论留言或私信…

竞赛选题 机器视觉的试卷批改系统 - opencv python 视觉识别

文章目录 0 简介1 项目背景2 项目目的3 系统设计3.1 目标对象3.2 系统架构3.3 软件设计方案 4 图像预处理4.1 灰度二值化4.2 形态学处理4.3 算式提取4.4 倾斜校正4.5 字符分割 5 字符识别5.1 支持向量机原理5.2 基于SVM的字符识别5.3 SVM算法实现 6 算法测试7 系统实现8 最后 0…

因为在此系统上禁止运行脚本

问题&#xff1a; 解决办法&#xff1a; vue项目搭建中"因为在此系统上禁止运行脚本"报错&#xff0c;解决方法 - 你的剧本 - 博客园 (cnblogs.com)

RDP协议流程详解(一)Connection Initiation阶段

Connetction Initiation是RDP连接的第一个阶段&#xff0c;具体包含两个消息RDP Negotiation Request和RDP Negotiation Response&#xff0c;下面结合协议数据包详细分析。 &#xff08;1&#xff09;RDP Negotiation Request 从数据包可以清晰看到此时的协议栈依次是TCP-TPKT…

反序列化漏洞

原理 反序列化是对象变成可以传输的字符串。 PHP反序列化的时候&#xff0c;基本都是围绕着serialize()&#xff0c;unserialize()这两个函数 serialize() 和 unserialize() 在 PHP内部没有漏洞的&#xff0c;产生反序列化漏洞是因为应用程序在处理对象、魔术函数以及序列化…

mysql面试题12:讲一讲MySQL中什么是半同步复制?底层实现?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:讲一讲mysql中什么是半同步复制?底层实现? MySQL中的半同步复制(Semi-Synchronous Replication)是一种复制模式,它在主服务器将数据写入到二…

10.2 调试事件获取DLL装载

理解了如何通过调试事件输出当前进程中寄存器信息&#xff0c;那么实现加载DLL模块也会变得很容易实现&#xff0c;加载DLL模块主要使用LOAD_DLL_DEBUG_EVENT这个通知事件&#xff0c;该事件可检测进程加载的模块信息&#xff0c;一旦有新模块被加载或装入那么则会触发一个通知…

k8s集群-6(daemonset job cronjob控制器)

Daemonset 一个节点部署一个节点 当有节点DaemonSet 确保全部 (或者某些) 节点上运行一个 Pod 的副本。加入集群时&#xff0c;也会为他们新增一个 Pod 。当有节点从集群移除时&#xff0c;这些Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 DaemonSet 的典型用…

Swift SwiftUI CoreData 过滤数据 1

Xcode: Version 14.3.1 (14E300c) iOS: 16 预览&#xff1a; Code: import SwiftUI import CoreDatastruct TodosSearch: View {State private var search_title "测试"FetchRequest var todos_search: FetchedResults<Todo>init() {let request: NSFetchReq…

《机器学习实战》学习记录-ch2

PS: 个人笔记&#xff0c;建议不看 原书资料&#xff1a;https://github.com/ageron/handson-ml2 2.1数据获取 import pandas as pd data pd.read_csv(r"C:\Users\cyan\Desktop\AI\ML\handson-ml2\datasets\housing\housing.csv")data.head() data.info()<clas…

Access注入---Cookie注入

Access注入----Cookie注入Access数据库&#xff08;微软&#xff09; 逐渐淘汰 &#xff08;没有库的概念&#xff0c;是表的集合&#xff09;Access没有系统自带库Cookie注入&#xff08;头注入HEAD注入的&#xff09;php中产生Cookie注入的可能性小&#xff0c;但ASP产生Cook…

代码随想录算法训练营第五十七天 | 动态规划 part 15 | 392.判断子序列、115.不同的子序列

目录 392.判断子序列思路代码 115.不同的子序列思路代码 392.判断子序列 Leetcode 思路 dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度为dp[i][j]递推公式&#xff1a; 初始化&#xff1a;为0遍历顺序&#xff…

【Spring】Bean作用域和生命周期

Bean作用域和生命周期 一. Bean 的作用域1. Bean 的 6 种作⽤域&#xff1a;①. singleton②. prototype③. request④. session⑤. application⑥. websocket单例作用域(singleton) VS 全局作⽤域(application) 2. 设置作用域 二. Spring 执行流程和 Bean 的生命周期1. Spring…

【实操记录】Oracle数据整库同步至Apache Doris

本文是Oracle数据整库同步至Apache Doris实操记录&#xff0c;仅供参考 参考&#xff1a;https://cn.selectdb.com/blog/104 1、Oracle 配置 [rootnode1 oracle]# pwd /u01/app/oracle [rootnode1 oracle]# mkdir recovery_area [rootnode1 oracle]# chown -R oracle:dba re…