当前位置: 首页 > news >正文

GUI07-学工具栏,懂MVC

MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。这节将安排您学习:

  1. Model-View-Controller 模式
  2. 如何创建工具栏以及如何于其上创建普通、多选、单选工具按钮
  3. 控件之间如何通过“空闲”事件实现状态统一

wxToolBar & MVC

0. 课堂视频

建议先看视频,再看文本教程。最后到 d2school 课堂做本课的学习强化练习。

GUI07-学工具栏,懂 MVC

1. 才不是题外话:MVC

MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。

MVC 是 “Model-View-Controller” 的简写:

  • Model / 模型:可认为就是我们在代码中定义的各种业务数据;
  • View / 视图:业务数据的展现形式,一种模型(数据)往往有多种展现形式;
  • Controller / 控制器: 用户通过控制器,以可定制的方式,获取数据模式,及指定形式展现(视图)。

程序员开发软件时,将代码按照 Model-View-Controller 加以分离,能让软件代码:

  1. 逻辑,意图更清晰
  2. 耦合更低
  3. 更可维护

MVC 比较适用于中大型软件代码的组织,我们前几节课所写的程序,看似简单,但其实, GUI软件没有小项目,是底层的库(比如 wxWidgets)默默地做出大量支持,包括 MVC 架构。

以前面课堂写的小例程为例:我们在窗体上鼠标位置下显示鼠标所在的坐标值,并且允许用户做如下控制:

  1. 是否显示坐标值,或仅显示一行提示文字;
  2. 文字以蓝或红哪种颜色显示。

则,至少有两个数据模型:

编号Model
M1表达坐标的两个整数:x, y
M2表达用户选中颜色的菜单项ID

以及,这两个数据,至少四种组合态的展现形式:

编号View (数据视图)
V1蓝色 + 显示坐标
V2红色 + 显示坐标
V3蓝色 + 不显示坐标(仅显示提示)
V4红色 + 不显示坐标(仅显示提示)

以下是实际运行时,显示的 V2 状态界面截图:
工具栏框架窗口运行效果
正如本课视频所讲到,View 并不仅仅包含业务数据的展现,用于实现和用户交互的 GUI 界面控制,比如我们已学的菜单、工具栏、状态栏等界面控件,也是 View 的组成。它们也会有和业务数据紧密关联的状态,比如菜单或工具图标的多选或单选状态。

以上归纳了 Model 和 View,那 Controller是什么呢?是控制流程。在我们所写的程序中,程序接收用户的输入(鼠标点击等),然后调用相应的事件函数,在事件函数中修改 Model 数据,最后引发视图刷新,包括业务视图刷新和人机交互界面中控件状态的改变,这整个过程即为 Controller。

初接触时,对 MVC 的三个最常见的误解为:

  • 误解一:以为 View的展现内容只能给看。正解:一个程序的输出可以是另一个程序的输入,此时可视为后者是前者的“用户”,同理,同一个程序的控制,也可能是来自另一个程序的输入。正因为 Views 不一定真实的人,所以在服务端程序中,特别是多层网络架构的软件系统中,MVC 的应用也广泛可见;

  • 误解二:以为人机交互过程中界面控件,就是 Controller 。正解:Controller 是接受用户(不一定是人,见上)的输入,然后引发(即动作的发起者)Model 被修改,并最终体现到 View 变化的每一个完整过程。

  • 误解三:以为只有业务数据的展现是 Views。正解:凡是需要展现给用户看的内容,基本都是 View,包括控件的状态。

2. 创建图标

在 Windows 系统下,应用程序工具栏按钮所需要的图标,需要使用 ICON 类型的图标,在 wxWidgets中,对应到 wxIcon 类。

2.1 从文件直接创建

可在程序运行时,通过读取指定路径(相对或绝对)读取指定的图标文件,以构造出一个wxIcon对象,示例代码:

wxIcon myIcon = wxIcon(wxT("路径/图标文件.ico"), wxBITMAP_TYPE_ICO, 16, 16);

注意,创建所得是普通的栈对象,非堆对象。

  • 入参1:图标的磁盘位置(包括路径和文件名,可使用绝对或相对路径);
  • 入参2:图标文件的类型(注意是 wxBITMAP_TYPE_ICO,而非 wxBITMAP_TYPE_ICON);
  • 入参3,4:两个整数,图标的长、宽(像素)。

在程序运行时读取外部文件以创建图标(或其它资源)——

  • 好处:可随时更换图标——不少应用程序支持 “换肤”,对于工具栏按钮来说,这是一种简便可行的方法;
  • 坏处:程序无法单独运行。比如你想把程序发给你的朋友,就得同时附上这些图标文件,并需确保路径正确。

2.2 从程序嵌入资源中创建

Windows 支持将一些资源,嵌入到可执行文件(.exe)“体内”,从而实现可执行文件可独立运行。

Code::Blocks 向导生成的 wxWidgets 项目中,已经自带 resource.rc 的文件,打开它,默认内容为:

aaaa ICON "wx/msw/std.ico"
#include "wx/msw/wx.rc"

默认包含的 wxWidgets 程序图标。其中,aaaa 为资源的名字,ICON 为资源类型,此处为图标,最后一列 “wx/msw/std.ico” 为图标在磁盘上的路径和名字(仅编译时需用到,运行时不再需要此路径)。

假设我们已经在当前项目下创建名为 icons 的子目录,并于其下准备好 about.ico、show_info.ico、blue_txt.ico、red_txt.ico、quit.ico 等图标,则可将 resouce.rc 内容修改成:

aaaa ICON "wx/msw/std.ico"about ICON  "icons/about.ico"
blue_txt ICON "icons/blue_txt.ico"
red_txt ICON "icons/red_txt.ico"
quit ICON "icons/quit.ico"
show_info ICON "icons/show_info.ico"#include "wx/msw/wx.rc"

这样,在编译后,相关图标资源就会内嵌在编译生成的可执行文件中,并可通过 wxIcon 的另一个构造函数读出并且成图标对象:

wxIcon icon = wxIcon(wxT("资源名"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);

比如,创建 quit 图标:

wxIcon iconQuit = wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);

本文后续代码均从内嵌资源创建图标。

3. 工具栏与工具栏按钮

3.1 创建工具栏

wxFrame::CreateToolBar() 用于创建一个空白的工具栏,该方法返回一个 wxToolBar * (指针)。

示例代码:

wxToolBar* tb = this->CreateToolBar(); // 创建工具栏

以上代码中的 this 工具栏所属的框架窗口,它也将负责该工具栏的生命周期(在框架窗口关闭前,将自释放上面创建工具栏堆对象)。

以下各种工具栏按钮,都需要由工具栏(wxToolBar)对象来创建。

3.2 普通工具按钮

使用工具栏对象,创建一个普通工具栏按钮,方法名为 “AddTool()”示例代码:

// 准备图标 (从内嵌资源中读取)
wxIcon iconQuit = wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);// 创建带图标的普通工具按钮
tb->AddTool(idMenuQuit, _("Quit"), iconQuit, _("Quit the Application"));
  • 入参1:工具按钮要执行的命令对应的ID,通常来自已经创建的菜单项所绑定的事件ID。比如本例的 idMenuQuit 为 “Quit” 菜单项的ID,该命令用于退出整个应用程序;
  • 入参2:工具按钮的标签,默认状态下并不显示,复杂情况下,可设置为在图标底部或右侧显示按钮的名字;
  • 入参3:前面创建的图标对象(并非指针);
  • 入参4:鼠标在该工具按钮上浮动时出现的提示。

也可将构造图标对象和创建工具按钮合成一步:

tb->AddTool(idMenuQuit, _("Quit"), wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16)_("Quit the Application"));

实际还需要第三步,但当连续为同一个工具栏创建多个工具按钮时,仅需在最后调用一次:

tb->Realize(); // 真实展现,最后调用,只需一次

仅在调用该方法后,工具栏才真正地将新创建的各工具按钮展现出来。

3.3 复选工具按钮

使用方法为:AddCheckTool(),示例代码:

//复选工具按钮(是否显示鼠标坐标)
tb->AddCheckTool(idMenuShowMotionInfo, _("Show Info"),wxIcon(wxT("show_info"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),wxNullBitmap, // 按钮变灰时显示的图标,由程序自动生成_("Show motion info or no")); // 提示

第四个入参用于指定,该复选按钮在不可用(disabled)状态下如何展现,除非你确实想为之提供一种特别的样子,否则,可如代码所示,指定使用代表空图片的对象 wxNullBitmap,系统将自动以 “灰度” 方式生成该状态的展现样式。

因为方法名已经是 “AddCheckTool ()”,故无需像普通的 “AddTool ()” 那样,再由入参指定按钮的类型,下面用于创建单选工具按钮的方法,也是如此。

3.4 单选工具按钮

使用方法为:AddRadioTool(),示例代码:

//单选工具按钮(两个:选择使用蓝色文本或使用红色文本)
tb->AddRadioTool(idMenuBlueText, _("Blue Text"),wxIcon(wxT("blue_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),wxNullBitmap, // 按钮变灰时显示的图标,由程序自动生成_("Set text blue")); // 提示tb->AddRadioTool(idMenuRedText, _("Red Text"),wxIcon(wxT("red_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),wxNullBitmap,_("Set text red"));

和复选按钮不同,单独一个单选按钮没有意义,通常需要接连创建一组,让用户从多个中选择一个(即为单选之意)。

同一工具栏上如有多组单选按钮,除了可考虑使用分隔(见下面小节)在视觉上加以分组之外,并不需要再额外在逻辑上分组,因为工具按钮通常对应到菜单项,而对菜单项,我们已经作了逻辑分组,详见 《第5节 玩转主菜单》。

3.5 分隔线

tb->AddSeparator(); // 分隔线

3.6 连续代码

以下是在示例项目中, wxToolBarFrame 构造函数尾部,创建工具栏及相应按钮、分隔线的代码片段:

    // 工具栏wxToolBar* tb = this->CreateToolBar(); // 创建工具栏wxIcon iconQuit = wxIcon(wxT("quit"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);tb->AddTool(idMenuQuit, _("Quit"), iconQuit, _("Quit the Application"));tb->AddSeparator(); // 分隔线//复选工具按钮(是否显示鼠标坐标)tb->AddCheckTool(idMenuShowMotionInfo, _("Show Info"),wxIcon(wxT("show_info"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),wxNullBitmap, // 按钮变灰时显示的图标,由程序自动生成_("Show motion info or no")); // 提示tb->AddSeparator(); // 分隔线// 单选工具按钮(两个)tb->AddRadioTool(idMenuBlueText, _("Blue Text"),wxIcon(wxT("blue_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),wxNullBitmap,_("Set text blue"));tb->AddRadioTool(idMenuRedText, _("Red Text"),wxIcon(wxT("red_txt"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16),wxNullBitmap,_("Set text red"));tb->Realize(); // 真实展现,最后调用,只需一次

4. 控件状态同步

为了使用方便,GUI 程序往往允许用户从不同控件入口发起操作,在本例,用户通过菜单栏或工具栏,都可以修改文字的颜色。窗体上输出的文字归属 View,但是菜单项或工具按钮的显示状态,也归于 View 范畴,它们的选中状态,必须保持同步。

举例:用户选中 “变帅” 菜单项,则 工具栏上 “变帅” 按钮也需要在操作后,变成“被按下”的状态;反过来也一样:用户按下 “变帅” 按钮,则同名的菜单项之前,必须打上勾。这还是复选控件,如果是单选控件,则需要的维护一组控件的状态,会更加啰嗦,容易出错。

因此,无论是大家比较熟悉的 Windows 或 苹果的 GUI 系统,还是 Linux 下的各种 GUI 桌面系统,或者是新兴的智能手机 Android 系统,或者是为浏览器前端开发提供支持各种前端库,基本都会提供一套机制,来辅助程序员实现界面组件的状态同步。

GUI 程序有一个共同点:它不可能很忙。有人说,我打开 Word,然后以平均每分钟 120 个汉字,接近 500 次按键的速度打字,这 Word 肯定忙坏了呀? 不是的,这点输入对现在的计算机和程序来说真是一点压力没有,程序仍然能在你的指法间隙间,“挤出”一大把无所事事的时间(不信你可以打开 Windows 任务管理器,看看你要能以怎样的打字速度,让 CPU 占用率提高 0.1%?)。

程序这么闲,自然就可以利用起来,闲着也是闲着,不如打打孩子——不是,不如去检查一下,有哪个控件状态不对,我们好把它纠正过来。

这种空闲事件,在很多 GUI 系统(比如 Windows 或 Android)中称为 “Idle-Event” (对应的事件处理器称为 “Idle-Handler”)。我们正在学习的 wxWidgets 又将它细分出一个 “wxUpdateUIEvent”,即专门用来处理用户界面(UI)的控件状态更新(Update)的事件。对应的,绑定事件函数的宏为:“EVT_UPDATE_UI”。

以用户可以切换坐标是否显示这一功能为例,按照 MVC 的划分原则,我们首先需要有的 Model 数据是:

  • a) 坐标数据 x,y (之前课堂已经添加了);
  • b) 是否显示,之前课堂没有添加,因此本课需为框架窗口类加上该成员数据,取名 showMotionInfo,一个 bool 值。

接着,当用户依赖某个操作路径(菜单或工具按钮),发起切换操作时,作为一个GUI开发框架,wxWidget将配合作为一个 GUI 操作系统的 Windows,共同帮我们完成复杂的 Controller 过程(视频里说的那些“线”),最终调用到我们写的事件响应函数,该函数修改作为 Model 数据之一的 showMotionInfo。如何知道将它修改成 true 或 false 呢?也就是说,如何知道用户当前操作是选中或是取消选中呢?仍然得感谢 wxWidgets 和其下的操作系统,它已经将该信息,放在事件数据中的 “IsCheck()” 方法里了。

接受用户输入,修改 Model 数据(showMotionInfo)的示例代码:

// 1 绑定到菜单上:
EVT_MENU(idMenuShowMotionInfo, HelloToolBarFrame::OnShowMotionInfo)...// 2 在事件响应函数中,修改 Model,状态信息在事件中:
void HelloToolBarFrame::OnShowMotionInfo(wxCommandEvent& event)
{this->showMotionInfo = event.IsChecked(); // 修改 model
}

接下来,程序在某个时刻发现自己很闲,于是它去开始检查并纠正哪个“孩子”(控件)状态不对——但是,它自己并不知道,也不记录具体哪个控件所应该处于正确状态是什么——谁知道,当然只有作为程序员的我们知道,所以程序会自动触发 UpdateUIEvent 事件,让我们在这个事件里去告诉它,某个“孩子”现在的正确状态应该是:在睡觉……如果有十个不同ID的控件需要更新状态,程序会触发十次这样的事件。

以 “idMenuShowMotionInfo” 为例,空闲的程序想知道绑定该ID的菜单项和工具图标当前应该处于什么状态时,它会触发以下的事件函数被调用:

// 3 绑定控件ID
EVT_UPDATE_UI(idMenuShowMotionInfo, HelloToolBarFrame::OnUpdateShowMotionInfo)...// 4 在事件中,由程序员告诉程序,当前控件的正确状态(是否选中)
void HelloToolBarFrame::OnUpdateShowMotionInfo(wxUpdateUIEvent& event)
{event.Check(this->showMotionInfo); // 有没有选中
}

请对比代码中的 3 和 4,从 “SET/写” 和 “GET/读” 的角度,加以理解。

以上讲的是控件的复选状态,它的状态就是 “选中” 或 “没选中”;对比之下,单选状态稍显复杂。因为单选状态的控件通常成组出现(至少两个),对应的详细状态应该是:“选中哪一个了?”。再次感谢所有 GUI 库,当它们在触发控件的 “UpdateEvent” 时,会带上这个控件的 ID,因此,我们只需检查它是不是我们记录的,用户选中的那个控件ID即可。

比如颜色选择有两项:蓝或红,当用户做出选择,我们就用 Model 数据(selectedColorId) 记录下来:

// 5 绑定控件ID,同一组单选控件需要全部绑定到同一个事件函数:
EVT_UPDATE_UI(idMenuBlueText, HelloToolBarFrame::OnUpdateTextColor)
EVT_UPDATE_UI(idMenuRedText, HelloToolBarFrame::OnUpdateTextColor)...// 6 记录用户选的是哪个ID
void HelloToolBarFrame::OnTextColorSelected(wxCommandEvent& event)
{selectedColorId = event.GetId();
}

对应的,当程序因为闲着也是闲着,又要 “打孩子” 时,我们是这样告诉它哪个 “孩子” 需要被选中,哪个 “孩子” 不需要:

// 7 同样需要绑定一组单选控件(的ID)
EVT_UPDATE_UI(idMenuBlueText, HelloToolBarFrame::OnUpdateTextColor)
EVT_UPDATE_UI(idMenuRedText, HelloToolBarFrame::OnUpdateTextColor)...// 8 在事件中,由程序员告诉程序,它来“问”的控件,是不是被选中的那个
void HelloToolBarFrame::OnUpdateTextColor(wxUpdateUIEvent& event)
{event.Check(event.GetId() == this->selectedColorId);
}

5 Model 数据

最后,汇总一下本例程用到的 Model 数据:

int xPos, yPos;int selectedColorId = idMenuBlueText;bool showMotionInfo = false; 

其中,前两项是在之前的课堂定义的。

相关文章:

GUI07-学工具栏,懂MVC

MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。这节将安排您学习: Model-View-Controller 模式如何创建工具栏以及…...

免费线上签字小程序,开启便捷电子签名

虽如今数字化飞速发展的时代,但线上签名小程序的开发制作却并非易事。需要攻克诸多技术难题,例如确保签名的真实性与唯一性,防止签名被伪造或篡改。 要精准地捕捉用户手写签名的笔迹特征,无论是笔画的粗细、轻重,还是…...

计算机的错误计算(一百八十九)

摘要 用大模型计算 tan(12.345) . 自变量取弧度。结果保留10位有效数字。不同于前面两节的大模型,本节调用了新的两个大模型。然而,很遗憾,它们给出的答案似乎仍然是“匹配”出来的,不是计算出来的。当然,均是错误的。…...

HDR视频技术之十一:HEVCH.265 的 HDR 编码方案

前文我们对 HEVC 的 HDR 编码优化技术做了介绍,侧重编码性能的提升。 本章主要阐述 HEVC 中 HDR/WCG 相关的整体编码方案, 包括不同应用场景下的 HEVC 扩展编码技术。 1 背景 HDR 信号一般意味着使用更多比特,一般的 HDR 信号倾向于使用 10…...

使用 AI 辅助开发一个开源 IP 信息查询工具:一

本文将分享如何借助当下流行的 AI 工具,一步步完成一个开源项目的开发。 写在前面 在写代码时,总是会遇到一些有趣的机缘巧合。前几天,我在翻看自己之前的开源项目时,又看到了 DDNS 相关的讨论。虽然在 2021 年我写过两篇相对详细的教程&am…...

『 Linux 』高级IO (一)

文章目录 内容回顾及铺垫五种IO模型不同类型IO的区别非阻塞IOfcntl( ) 多路转接 - select( )select( ) 的基本使用 - SelectServer服务器 内容回顾及铺垫 在博客『 Linux 』基础IO/文件IO (万字)中介绍了对IO的认识; IO实际上为Input/Output,输入输出; 以网络协议栈的视角来看,…...

Cisco WebEx 数据平台:统一 Trino、Pinot、Iceberg 及 Kyuubi,探索 Apache Doris 在 Cisco 的改造实践

导读:Cisco WebEx 早期数据平台采用了多系统架构(包括 Trino、Pinot、Iceberg 、 Kyuubi 等),面临架构复杂、数据冗余存储、运维困难、资源利用率低、数据时效性差等问题。因此,引入 Apache Doris 替换了 Trino、Pinot…...

Java - 日志体系_Apache Commons Logging(JCL)日志接口库

文章目录 官网1. 什么是JCL?2. JCL的主要特点3. JCL的核心组件4. JCL的实现机制5. SimpleLog 简介6. CodeExample 1 : 默认日志实现 (JCL 1.3.2版本)Example 2 : JCL (1.2版本) Log4J 【安全风险高,请勿使用】 7. 使用…...

Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02

在嵌入式开发中,I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,广泛应用于与外设(如 EEPROM、传感器、显示屏等)进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器,它提供 2Kbit…...

盒子模型(外边距的设置)

用于页面中元素的合理布局所有的元素都可以有宽高所有元素都是一个矩形所有元素都可以看成一个盒子盒子包括 外边距边框内边距元素内容 外边距设置 外边距的要素:top、bottom、left、right外边距的尺寸:合法的尺寸单位外边距语法:marign-方…...

买卖股票的最佳时机 IV - 困难

************* C topic&#xff1a;188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09; ************* Stock angin: Still stocks. Intuitively, it feels hard. For once: class Solution { public:int maxProfit(vector<int>& prices) {in…...

ElasticSearch - 深入解析 Elasticsearch Composite Aggregation 的分页与去重机制

文章目录 Pre概述什么是 composite aggregation&#xff1f;基本结构after 参数的作用问题背景&#xff1a;传统分页的重复问题after 的设计理念响应示例 after 如何确保数据不重复核心机制Example步骤 1: 创建测试数据创建索引插入测试数据 步骤 2: 查询第一页结果查询第一页返…...

HTML5 Web IndexedDB 数据库

IndexedDB 是一种基于浏览器的 NoSQL 数据库&#xff0c;用于在客户端持久化存储大量结构化数据。 IndexedDB 允许通过键值对存储复杂的数据对象&#xff08;如对象、数组、文件等&#xff09;&#xff0c;并支持事务、索引、版本控制和复杂查询操作。 IndexedDB 是异步的&am…...

苏黎世联邦理工学院与加州大学伯克利分校推出MaxInfoRL:平衡内在与外在探索的全新强化学习框架

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

读书笔记~管理修炼-缄默效应

缄默效应&#xff1a;学会正确批评下属 员工明明犯了错误&#xff0c;却不及时告知你&#xff0c;总是拖到最后一刻无法弥补时才不得不承认出了问题——你遇到过这样的问题吗&#xff1f; 这其实是缄默效应在发挥作用。 在职场中&#xff0c;即使再扁平化的环境&…...

LabVIEW声音信号处理系统

开发了一种基于LabVIEW的声音信号处理系统&#xff0c;通过集成的信号采集与分析一体化解决方案&#xff0c;提升电子信息领域教学与研究的质量。系统利用LabVIEW图形化编程环境和硬件如USB数据采集卡及声音传感器&#xff0c;实现了从声音信号的采集到频谱分析的全过程。 项目…...

2024.12.10——攻防世界Web_php_include

知识点&#xff1a;代码审计 文件包含 伪协议 伪协议知识点补充&#xff1a; 在PHP中&#xff0c;伪协议&#xff08;Pseudo Protocols&#xff09;也被称为流包装器&#xff0c;这些伪协议以 php://开头&#xff0c;后面跟着一些参数&#xff0c;用于指定要执行的操作或需要…...

Linux shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量转PDF文件

Linux Debian12基于ImageMagick图像处理工具编写shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量转PDF文件&#xff0c;”多个图片分开生成多个PDF文件“或者“多个图片合并生成一个PDF文件” 在Linux系统中&#xff0c;使用ImageMagick可以图片格式转换&#xff0c…...

有没有检测吸烟的软件 ai视频检测分析厂区抽烟报警#Python

在现代厂区管理中&#xff0c;安全与规范是重中之重&#xff0c;而吸烟行为的管控则是其中关键一环。传统的禁烟管理方式往往依赖人工巡逻&#xff0c;效率低且存在监管死角&#xff0c;难以满足当下复杂多变的厂区环境需求。此时&#xff0c;AI视频检测技术应运而生&#xff0…...

LeetCode 每日一题 2024/12/16-2024/12/22

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 12/16 1847. 最近的房间12/17 3291. 形成目标字符串需要的最少字符串数 I12/18 3292. 形成目标字符串需要的最少字符串数 II12/19 3285. 找到稳定山的下标12/20 3138. 同位…...

gitlab代码推送

点击这个√ 修改的文件全部选上 填好提交的名称 点击commit 选取提交的 gitlab 库 点击Push...

小红书飞书素材库 | AI改写 | 无水印下载 | 多维表格 | 采集同步 | 影刀RPA

小红书飞书素材库 | AI改写 | 无水印下载 | 多维表格 | 采集同步 | 影刀RPA 模板准备 进入【小红书】素材采集库_荷逸模板&#xff0c;点击使用模板 创建文档应用 在开发者后台 - 飞书开放平台创建 企业自建应用 (需要账号有相应的权限, 如果没有权限向管理员申请) 获取 Ap…...

【计算机视觉基础CV-图像分类】02-入门详解图像分类、经典数据集、比赛与冠军图像模型演进史

前言 图像分类&#xff08;Image Classification&#xff09;是计算机视觉&#xff08;Computer Vision&#xff09;中一项基础且核心的任务。简单来说&#xff0c;就是让计算机从给定的类别集合中&#xff0c;为一张输入图片分配一个正确的类别标签。这个过程听起来直观&…...

【机器学习】探索机器学习与人工智能:驱动未来创新的关键技术

探索机器学习与人工智能&#xff1a;驱动未来创新的关键技术 前言&#xff1a;人工智能的核心技术深度学习&#xff1a;自然语言处理&#xff08;NLP&#xff09;&#xff1a;计算机视觉&#xff1a; 机器学习与人工智能的驱动创新医疗健康领域金融行业智能制造与工业互联网智慧…...

DS二叉树--基于数组存储的构建

题目描述 任意二叉树可以根据完全二叉树性质保存在一个数组中。已知二叉树的数组存储&#xff0c;用程序构建该二叉树。 提示&#xff1a;用递归方法或非递归都可以 输入 第一行输入一个整数t&#xff0c;表示有t个测试数据 第二行起输入二叉树的数组存储结果&#xff0c;空…...

入侵他人电脑,实现远程控制(待补充)

待补充 在获取他人无线网网络密码后&#xff0c;进一步的操作是实现入侵他人电脑&#xff0c;这一步需要获取对方的IP地址并需要制作自己的代码工具自动化的开启或者打开对方的远程访问权限。 1、获取IP地址&#xff08;通过伪造的网页、伪造的Windows窗口、hook&#xff0c;信…...

STM32基于标准库如何查看时钟主频,100%简单

基于原有的工程写入两行代码&#xff0c;见下图 RCC_ClocksTypeDef get_rcc_clock; RCC_GetClocksFreq(&get_rcc_clock); 进入我们的仿真加入断点&#xff0c;然后在watch1观察变量值数据&#xff0c;然后在计算器计算就能得出&#xff0c;如上图。 但是这样看的PAB1上…...

HarmonyOS NEXT 技术实践-基于意图框架服务实现智能分发

在智能设备的交互中&#xff0c;如何准确理解并及时响应用户需求&#xff0c;成为提升用户体验的关键。HarmonyOS Next 的意图框架服务&#xff08;Intents Kit&#xff09;为这一目标提供了强大的技术支持。本文将通过一个项目实现的示例&#xff0c;展示如何使用意图框架服务…...

[原创](Modern C++)现代C++的第三方库的导入方式: 例如Visual Studio 2022导入GSL 4.1.0

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共23年] 职业生涯: 21年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi、XCode、Eclipse…...

【jenkins插件】

1) 2) 3) 4) 5) 6) 参考: 知识库/运维/Jenkins/01-安装/13-插件.md zfoo/java-developer-document - 码云 - 开源中国...

springboot472基于web网上村委会业务办理系统(论文+源码)_kaic

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本网上村委会业务办理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数…...

七层网络笔记

首先&#xff0c;用户感知到的只是最上面一层应用层&#xff0c;自上而下每层都依赖于下一层&#xff0c;所以我们从最下一层开始切入&#xff0c;比较好理解 每层都运行特定的协议&#xff0c;越往上越靠近用户&#xff0c;越往下越靠近硬件 物理层由来&#xff1a;上面提到&a…...

PostgreSQL编译安装教程

下载安装 1.在家目录创建一个文件夹放下载安装包 mkdir softwarecd software 2.下载文件压缩包 wget https://ftp.postgresql.org/pub/source/v16.0/postgresql-16.0.tar.gz 3.解压 tar -xzvf postgresql-16.0.tar.gz 4.编译 在software/postgresql-16.0下 cd software…...

音视频学习(二十四):hls协议

基本原理 HLS协议通过将视频文件切分成多个小的媒体段&#xff08;通常是10秒左右的.ts文件&#xff09;&#xff0c;并通过HTTP传输给客户端。视频播放过程中&#xff0c;客户端按顺序请求这些小段文件来逐步播放整个视频流。HLS还支持多种码率&#xff0c;以便适应不同网络条…...

pytorch MoE(专家混合网络)的简单实现。

专家混合&#xff08;Mixture of Experts, MoE&#xff09;是一种深度学习模型架构&#xff0c;通常用于处理大规模数据和复杂任务。它通过将输入分配给多个专家网络&#xff08;即子模型&#xff09;&#xff0c;然后根据门控网络&#xff08;gating network&#xff09;的输出…...

代码随想录day24 | leetcode 93.复原IP地址 90.子集 90.子集II

93.复原IP地址 Java class Solution {List<String> result new ArrayList<String>();StringBuilder stringBuilder new StringBuilder();public List<String> restoreIpAddresses(String s) {backtracking(s, 0, 0);return result;}// number表示stringb…...

Scala项目(图书管理系统)

3、service BookService package org.app package serviceimport org.app.dao.{BookDAO, BorrowRecordDAO} import org.app.models.{BookModel, BorrowRecordModel}import java.time.LocalDateTime import scala.collection.mutable.ListBuffer// 图书业务逻辑层 class BookS…...

Deepin/Linux clash TUN模式不起作用,因网关导致的问题的解决方案。

网关导致的问题的解决方案 查看路由 ip route寻找默认路由 默认路由应当为Mihomo default dev Mihomo scope link 如果不是&#xff0c;则 sudo ip route add default dev Mihomo在clash TUN开关状态发生变化时&#xff0c;Mihomo网卡会消失&#xff0c;所以提示找不到网卡…...

【macos java反编译工具Java Decompiler】

mac上能用的反编译工具 https://java-decompiler.github.io/...

VLAN数据格式

概念&#xff1a;VLAN叫做虚拟局域网&#xff0c;指在物理网络中根据用于、工作组、应用等进行逻辑划分的局域网&#xff0c;是一个广播域&#xff0c;与用户的物理位置没有关系。 作用&#xff1a;VLAN可以灵活的进行分段和组织&#xff0c;能够实现更好的安全性&#xff0c;…...

Error response from daemon: Get “https://registry-1.docker.io/v2/“ 问题解决

文章目录 一、参考资料二、修改nameserver三、修改daemon.json文件 一、参考资料 问题的根源在于系统每次都会自动修改DNS&#xff0c;所以需要永久修改 linux永久修改dns 二、修改nameserver sudo nano /etc/resolvconf/resolv.conf.d/head 没有该文件的话需要安装 sudo a…...

每天40分玩转Django:Django部署

Django部署 一、今日学习内容概述 学习模块重要程度主要内容生产环境配置⭐⭐⭐⭐⭐settings配置、环境变量WSGI服务器⭐⭐⭐⭐⭐Gunicorn配置、性能优化Nginx配置⭐⭐⭐⭐反向代理、静态文件安全设置⭐⭐⭐⭐⭐SSL证书、安全选项 二、生产环境配置 2.1 项目结构调整 mypr…...

学习threejs,scene.overrideMaterial全局材质效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.2 ☘️THREE.Scene 场景1.2 ☘️…...

新版Android Studio 2024.1.2版本,如何通过无线wifi连接手机实现交互

1、首先&#xff0c;先确定手机是否启动了开发者选项 在我的设备 -> 全部参数 -> MIUI版本点击6下 &#xff08;有的手机是 关于手机 -> 查看手机版本 &#xff09; 2、在设置中搜索 开启开发者选项 3、进入开发者选项后&#xff0c;在 调试 中选择 无线调试并选择…...

PTA 时间几何

作者 Happyer 单位 湖北文理学院 乘火车或飞机常有由始发时间历经时间计算终到时间的事儿。我们通过三个 函数来完成&#xff0c;当然&#xff0c;为了存储几点几分这个时间&#xff0c;我们专门定义了一个结构体Time_gxx,你要完成的是写二个函数&#xff1a;1&#xff09;st…...

事务、管道

目录 事务 相关命令 悲观锁 乐观锁 管道 实例 Pipeline与原生批量命令对比 Pipeline与事物对比 使用Pipeline注意事项 事务 相关命令 命令描述discard取消事务&#xff0c;放弃执行事务块内的所有命令exec执行所有事务块内的事务&#xff08;所有命令依次执行&#x…...

深入了解蓝牙Profile类型与设备的对应关系

在现代技术中,蓝牙作为一种无线通信技术,广泛应用于各种设备之间的短距离通信。不同的设备在连接时使用不同的蓝牙Profile(配置文件),每种Profile都为特定的设备功能提供支持,例如音频流传输、语音通话、文件传输等。在本文中,我们将详细介绍蓝牙Profile的常见类型及其对…...

net_device结构

net_device是Linux内核中用于表示网络设备的数据结构,它存储了特定网络设备的所有信息,无论是真实设备(如Ethernet)还是虚拟设备(如Bonding或VLAN)。以下是对net_device的详细解析: 一、定义与位置 net_device数据结构定义在Linux内核的include/linux/netdevice.h文件中…...

DuetWebControl 开源项目常见问题解决方案

DuetWebControl 开源项目常见问题解决方案 DuetWebControl A completely new web interface for the Duet electronics [这里是图片001] 项目地址: https://gitcode.com/gh_mirrors/du/DuetWebControl 一、项目基础介绍 DuetWebControl 是一个为 RepRapFirmware 设计的完全响…...

c# 不同数据类型转换

namespace Systempublic static class ConvertExtension {public static byte[] ToBinaryByteArray(this byte[] bytes){// 每个字节有 8 位&#xff0c;所以总位数为 bytes.Length * 8byte[] binaryArray new byte[bytes.Length * 8];int index 0;// 遍历每个字节foreach (b…...