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; 

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

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

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

相关文章

Chrome 关闭自动添加https

Open Chrome and go to “chrome://net-internals/#hsts”

重拾设计模式--外观模式

文章目录 外观模式(Facade Pattern)概述定义 外观模式UML图作用 外观模式的结构C 代码示例1C代码示例2总结 外观模式(Facade Pattern)概述 定义 外观模式是一种结构型设计模式,它为子系统中的一组接口提供了一个统一…

gitlab代码推送

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

echarts画风向杆

1.安装echarts 2.引入echarts 4.获取数据,转换数据格式 windProfile.title.text ${moment(time.searchTime[0], ‘YYYY-MM-DD HH:mm:ss’).format( ‘YYYY-MM-DD HH:mm’ )}-${moment(time.searchTime[1], ‘YYYY-MM-DD HH:mm:ss’).format(‘YYYY-MM-DD HH:mm’)…

Java字符串的|分隔符转List实现方案

字符串处理 问题背景代码实现代码优化原因分析实现方案 注意事项异常处理Maven未识别异常 问题背景 在项目组对账流程中,接收对方系统的对账文件,数据以|为分隔符,读取文件内容,分条入库。 代码实现 Java中将字符串转给list&am…

「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台

本篇将带你实现一个虚拟音乐控制台。用户可以通过界面控制音乐的播放、暂停、切换歌曲,并查看当前播放的歌曲信息。页面还支持调整音量和动态显示播放进度,是音乐播放器界面开发的基础功能示例。 关键词 UI互动应用音乐控制播放控制动态展示状态管理按钮…

iOS从Matter的设备认证证书中获取VID和PID

设备认证证书也叫 DAC, 相当于每个已经认证的设备的标识。包含了 VID 和 PID. 根据 Matter 对于设备证书的规定,DAC证书subject应该包含VID 和 PID. 可通过解析 X509 证书读取subject 来获得信息。 1 通过 SPM 添加X509 git地址:https://github.com/ap…

计算机毕业设计PyFlink+Hadoop广告推荐系统 广告预测 广告数据分析可视化 广告爬虫 大数据毕业设计 Spark Hive 深度学习 机器学

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

(2024.12)Ubuntu20.04安装openMVS<成功>.colmap<成功>和openMVG<失败>记录

一、安装openMVS 官方文档:https://github.com/cdcseacave/openMVS/wiki/Building sudo apt-get -y install git mercurial cmake libpng-dev libjpeg-dev libtiff-dev libglu1-mesa-dev eigen git clone https://gitlab.com/libeigen/eigen --branch 3.4 mkdi…

UE5 猎户座漂浮小岛 12 技能 瞬移 重力控制

1. 瞬移 1.1. 显示鼠标光标 “事件开始运行”添加显示鼠标逻辑 1.2. 释放技能蓝图 设置技能键 编写蓝图 1.3. 瞬移最大距离 2. 重力控制 2.1. 添加输入与动画 映射 重定向得到动画 新增状态FIRE_GracityControl 设置动画姿势 新增变量 切换动画 2.2. 技能蓝图(…

叉车作业如何确认安全距离——UWB测距防撞系统的应用

叉车在工业环境中运行,常常需要在狭窄的空间内完成货物的搬运和堆垛,这对操作员的技术水平和安全意识提出了极高的要求。传统的叉车作业依赖操作员的经验和视觉判断来确认安全距离,然而这种方式往往存在误差,特别是在视线受阻或光…

深度学习每周学习总结J9(Inception V3 算法实战与解析 - 天气识别)

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结Inception V1 简介Inception V3 简介1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数&#xff1…

记录仪方案_记录仪安卓主板定制_音视频记录仪PCBA定制开发

记录仪主板采用了强大的联发科MTK8768处理器,拥有出色的性能表现。它搭载了四个主频为2.0GHz的Cortex-A53核心与四个主频为1.5GHz的Cortex-A53核心,确保了高效的处理速度。此外,主板配备了4GB的RAM(可选8GB),并且内置64GB的ROM(可…

梳理你的思路(从OOP到架构设计)_简介设计模式

目录 1、 模式(Pattern) 是较大的结构​编辑 2、 结构形式愈大 通用性愈小​编辑 3、 从EIT造形 组合出设计模式 1、 模式(Pattern) 是较大的结构 组合与创新 達芬奇說:簡單是複雜的終極形式 (Simplicity is the ultimate form of sophistication) —Leonardo d…

JavaScriptEs6 - String类和Array类扩展内容

title: Javascript-ES6扩展写法 date: 2024-12-23 00:12:19 推荐在我的个人博客网站上访问本文章:shenying.website String 对象扩展 模版字符串 类似字符串的写法,用 来包裹字符串,优点是可以不用反斜杠就能在代码中多行编辑。对于模版字…

图书管理系统:提升图书馆服务质量的技术解决方案

可行性分析 在项目进行开发之前,必须要有可行性分析报告,分别从技术角度,经济角度,操作角度上面进行分析,经过可行性分析是实现科学开发的必要步骤。 3.1.1技术可行性 从技术的角度出发,目前采用开发的技术…

Unity中有什么情况下是需要用UniTask替代其他异步方式的吗?

在Unity开发中,是否需要使用UniTask替代其他异步方式(如Coroutine或Task),取决于项目需求、代码风格和性能考量。UniTask是一个第三方库,主要用于优化和简化Unity环境下的异步编程,它提供了诸多优势&#x…

NLP 中文拼写检测开源-01-基于贝叶斯公式的拼写检查器 CSC

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法,如果提升 100W 倍的性能? NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正?可我只会写 CRUD 啊! 一个提升英文单词拼…

SpringBoot核心:自动配置

有使用过SSM框架的,还记得曾经在spring-mybatis.xml配置了多少内容吗?数据源、连接池、会话工厂、事务管理,而现在Spring Boot告诉你这些都不需要了,简单的几个注解统统搞定,是不是很方便! 前言 SpringBoo…

重温设计模式--职责链模式

文章目录 职责链模式的详细介绍C 代码示例C示例代码2 职责链模式的详细介绍 定义与概念 职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它旨在将请求的发送者和多个接收者解耦,让多个对象都有机会处理请求&a…