OPC Client第5讲(wxwidgets):初始界面的事件处理;按照配置文件初始化界面的内容
接上一讲,即实现下述界面的事件处理代码;并且按照配置文件初始化界面的内容(三、)
事件处理的基础知识,见下述链接五、
OPC Client第3讲(wxwidgets):wxFormBuilder;基础框架;事件处理_wxwidgets 界面设计工具有哪些-CSDN博客
一、总体逻辑
1、涉及到事件处理的 控件
上图的每个序号都涉及到一个控件的事件处理,具体见二、
2、没有涉及到事件处理的 控件
上图中剩下的文本控件wxTextCtrl框,包括“选择机型和PLC”的勾选部分。即界面的初始化内容都是通过OnInitConf函数填的,没有涉及到事件处理。
二、按照一、中逻辑 实现 涉及到事件处理的控件
1、“选择机型和PLC”:OnCheckListBox函数
即下图的1 2 3
1>逻辑思考
先看“选择机型和PLC”这部分的实现代码(见上一讲三、2、2>和三、3、)
具体实现此界面的代码,在InitElement函数中,如下图
其中checkListBox、checkListBoxHCPlc 和 checkListBoxBHPlc三个变量都定义在.h中,在构造函数中实现初始化(为了简化代码)
所以,事件处理 涉及 checkListBox、checkListBoxHCPlc 和 checkListBoxBHPlc三个变量。
2>代码实现
1》三个变量分别绑定其事件函数,都是OnCheckListBox函数
- EVT_LISTBOX:用于wxListBox控件。
- 触发条件:当用户在wxListBox中选择一个不同的项时,该事件会被触发。
- EVT_CHECKLISTBOX:用于wxCheckListBox控件。
- 触发条件:当用户勾选或取消勾选wxCheckListBox中的任何一个选项时,该事件会被触发
注意下述链接五、
OPC Client第3讲(wxwidgets):wxFormBuilder;基础框架;事件处理_wxwidgets库-CSDN博客
综上,写出此部分的代码:
如下图,由于三个变量的Id都是wxID_ANY,所以在OnCheckListBox函数中需要先获取当前点击的选项的id【即传入参数wxCommandEvent& event的id】。
再根据判断条件 确认 当前勾选的选项是 哪个变量。
2》选中checkListBox
要求:
- 勾选了checkListBox里的选项后,默认勾选checkListBoxHCPlc里对应的禾川PLC
- 如果取消当前这个checkListBox,那么checkListBoxBHPlc和checkListBoxHCPlc对应的勾选都要取消
- 需要设置,checkListBoxHCPlc 和 checkListBoxBHPlc 两个选项只能勾选其一【在3》4》中实现】
区别:
“选中”指的是通过键盘方向键高亮的项(类似于焦点);而“勾选”才是用户点击复选框打钩的状态。
event.GetSelection()
- 这个方法是从 wxCommandEvent 对象中调用的。
- 它返回的是触发事件的那个特定项的索引(即用户最近一次点击或选择了哪个项)。
- 适用于在事件处理函数中获取用户最近一次操作的具体目标项。
checkListBox->GetSelection()
- 这是从 wxCheckListBox 控件对象本身调用的方法。
- 在 wxWidgets 中,对于 wxListBox 或类似的单选控件,GetSelection() 返回的是当前被选中的单个项的索引。如果没有任何项被选中,则返回值可能是 -1。
- 对于允许多选的控件(如 wxCheckListBox),这个方法通常并不适用于获取所有选中的项,而是用于获取最后一个被选中的项(如果有这样的实现)。
checkListBox->GetSelections(wxArrayInt&)
这是一个从 wxListBox 继承来的函数。
它返回的是 当前“选中”(高亮)的项索引列表
checkListBox->GetCheckedItems(wxArrayInt&)
获取所有被选中(勾选)项的索引列表。
这些方法直接从控件本身调用,可以用来查询当前控件的状态,而不仅仅是最近一次用户交互的结果。
3》选中checkListBoxHCPlc
相关基础知识见2》
要求:
- 需要设置,checkListBoxHCPlc 和 checkListBoxBHPlc 两个选项只能勾选其一
- 【新增】点击checkListBoxHCPlc时,如果checkListBox没有勾选,则自动勾选上
4》选中checkListBoxBHPlc
和3》完全相同,代码只是需要把3》中的HC与BH互换
2、“选择文件(右键)”:直接写在InitElement函数中了,在实现控件后直接用Bind的Lambda匿名方法
即下图的4 5
先看“选择文件(右键)”这部分的实现代码(见上一讲四、)
1>“标准对照(必需)”处的事件处理
用到的是下述链接六、2、的文件和目录对话框:wxFileDialog
OPC Client第4讲(wxwidgets):窗口布局基础知识;界面练习-CSDN博客
1》实现代码:创建wxFileDialog的参数
2》源代码累赘:不用再次调用event.Skip!
《1》对于事件处理机制:加上event.Skip()没用
先理解第3讲的事件处理运行过程五、1、3>
OPC Client第3讲(wxwidgets):wxFormBuilder;基础框架;事件处理-CSDN博客
上图代码中的理解:
- Lambda 表达式 没有父类,但是有父窗口[this],即InitFrame。【为什么?见上述链接五、1、3>的举例】
- 当加上event.Skip()后,wxMouseEvent&事件不属于wxCommand事件,所以这个事件不会向上传递到父窗口InitFrame里面。加上event.Skip()没用。
《2》wxTextCtrl还有一个wxMouseEvent类型的wxEVT_RIGHT_DOWN的默认行为:一旦你绑定了自己的事件处理函数,框架就不再自动执行默认行为
如何知道哪些事件有默认行为?——查阅官方文档
-
例如,
wxTextCtrl
对右键点击事件默认会显示一个上下文菜单,提供复制、粘贴等功能。 -
2>“批量连接”的事件处理
完全同1>
3、“确认”:OnConfirm函数【先看三、此处创建了MainFrame.h/.cpp】
即下图的6
1>为“确认”按钮绑定事件
2>事件处理函数OnConfirm的总体逻辑
1》更新三、中的config(额外创建变量config1,不改变config的值)
config1的Key值 等于 三、的Configuration.json文件里的Key值
2》把新的配置信息config1写入配置文件Configuration.json
《1》在my_lnit.h中 创建“写入配置文件WriteConfigurations”函数
《2》在InitFrame.cpp的OnConfirm函数中进行使用
3》关闭 InitFrame 对应的界面,打开 MainFrame界面,把1》的config1传给 MainFrame
《1》创建MainFrame.h和MainFrame.cpp
《2》在InitFrame.cpp的OnConfirm函数中进行使用
《3》在进入MainFrame后,即实现下图界面,具体内容见下一讲
4、“取消”:OnCancel函数
即下图的7
三、按照一、中逻辑 实现 没有涉及到事件处理的控件
上图中剩下的文本控件wxTextCtrl框,包括“选择机型和PLC”的勾选部分。即界面的初始化内容都是通过OnInitConf函数填的,没有涉及到事件处理。
1、OnInitConf函数作用:读取配置文件,初始化各个wxTextCtrl控件的默认值。
2、如何读取1、的配置文件?——新建my_lnit.h 和 my_lnit.cpp
仿照源代码,另一种更简便的写法如下
如上图,创建了读取配置文件的GetConfigurations函数。
在这个函数中,需要打开Configuration.json文件(下述2>),获取里面的数据,到InitFrame.cpp的config变量中。
1>给各个.h代码加上命名空间 + 把.h和.cpp文件放在对应文件夹中
1》新建include文件夹, 所有的命名空间都放在include文件夹下了
打开上图的include文件夹,再创建下图的五个文件夹。
下图的一个文件夹就是一个命名空间(主要用的是UaApp和uasdk),分别代表:缓冲区,json库,主项目相关,sdk相关
2》往1》的命名空间中移入.h文件,确保.cpp代码中#include <uasdk/my_Init.h>可以找到
在代码的“项目”->“属性”中,添加“附加包含目录的路径”
这里只是导入.h文件的路径,在下述链接四、3、
OPC Client第2讲:Visual Studio的C/C++使用教程;C++程序运行过程的各个文件;如何导入库?{静/动态库;更便捷的方法添加第三方库:使用属性表【配置使用wxwidgets】}_visual studio 运行c++-CSDN博客
如此,在.cpp中能引用uasdk文件夹下的.h文件了
3》在2》后出现问题:代码中头文件下的.h文件打不开了
即把.h和.cpp放在文件夹,怎么找到其的文件路径,并打开其代码
解决办法:
使用“添加现有项”并选择适当的过滤器
-
右键点击项目中的文件夹(”头文件“),然后选择“添加 -> 现有项...”。
-
导航到
D:\VisualStudio\OPC_Data\test\include
目录。 -
选择需要添加的
.h
文件。
同理,新建src文件夹,里面放入所有的.cpp文件。按照上述解决办法重新导入各个.cpp文件
4》【非必需】在每个.h代码中加上其属于哪个命名空间
这样不用每次在include文件夹里找
5》同理,修改InitFrame.h和InitFrame.cpp的文件位置和命名空间
main.cpp也要修改。
6》最后,所有的.h和.cpp文件都被放在了对应文件夹中。代码中也加入了每个.h应该放的命名空间
2>实现my_Init.h里的GetConfigurations函数
1》在文件夹中创建 Configuration.json 格式的文件,里面存放着初始的配置信息
注意,师傅发的源代码文件压缩包,这个Configuration.json文件是已经有了的,不用自己再创建
//所有的文件路径都是Debug目录下开始的,即exe文件所在的文件夹
再添加两个表格.xlsx在路径里面,因为在 Configuration.json文件 中需要这两个表格
Configuration.json文件里面存放着初始的配置信息
《1》注意:【自己写的Configuration.json文件 相比 师傅的做了修改】
1)师傅的——没必要用.json格式的文件
师傅的这个.json文件里存放的数据不是json格式,获取里面的数据也没有用到json包里的简便函数!
师傅用2》的.json库只是为了:在my_lnit.h的GetConfigurations函数中,声明的config变量 和 返回的数据是json格式。
需要读取两个.xlsx文件里的值
2)自己修改后的
就是改成json格式,利用2》的nlohmann json库里的函数 获取/修改数据
2》导入json库(GetConfigurations函数中,声明的config变量 和 返回的数据是json格式)
在源代码中选择了法2:
c++中nlohmann json的基本使用教程 - LiuYanYGZ - 博客园
不知道为什么,上述命令行报错说找不到json.hpp文件。那么换种方法,见下述链接
windows下使用#include <nlohmann/json.hpp>_nlohmann windows-CSDN博客
为了清楚知道nlohmann json有哪些函数可以用,把.hpp文件添加到项目目录中
《1》什么是hpp文件?
.hpp
更加明确地表示这是一个C++头文件,而 .h
则可能是C或C++的头文件。
然而,这并不是一个严格的规定,更多是一个社区内的约定俗成。在实际开发中,你可能会看到两者都被广泛使用。
《2》在代码中要用到此库的地方#include
3》实现GetConfigurations函数【见1》,自己写的对比师傅的优化了】
在这个函数中,需要打开Configuration.json文件(上述1》,文件操作见下述链接),利用nlohmann json(上述2》,使用见下述链接)里的函数获取里面的数据,到InitFrame.cpp的config变量中。
C++核心编程 | welcome to here
GitHub - nlohmann/json: JSON for Modern C++
4》上图中省略了 记录错误 的部分,见下一讲:创建logger.h和helper_t.h(3、中创建)里的gettime函数
3、实现InitFrame.h的OnInitConf函数
剩下的文本控件wxTextCtrl框,包括“选择机型和PLC”的勾选部分。即界面的初始化内容都是通过OnInitConf函数填的,没有涉及到事件处理。
在InitFrame构造函数中加入OnInitConf函数,如下图
实现OnInitConf函数。下图中省略了最外面的第二、三块的变量,其完全类似第一块
1>为什么不能直接odbcNameText->SetValue(config["clientname"]);
因为config["clientname"] 返回的是 json 类型的对象,不能直接传给wxTextctrl的SetValue。
- wxTextctrl的SetValue接受的是wxString 或者 std::string,但不接受 json 类型
- 为什么可以接受std::string?——存在隐式转换
2>上图红框:“选择机型和PLC”的勾选部分【创建helper_t.h】
注意,师傅的helper_t.h是SDK库里的,不是自己写的 !!!
split函数得自己实现!
- 在C++的标准库中确实没有直接名为
split
的函数,不过可以通过其他标准库功能来实现字符串分割的功能。常用的方法包括使用std::stringstream
(位于<sstream>
头文件中)
1》注意:getline函数的作用,以及分隔符开头/结尾、连续的分隔符:都会变成空字符串
下面开始在InitFrame.cpp的OnInitConf函数中进行调用
相关文章:

OPC Client第5讲(wxwidgets):初始界面的事件处理;按照配置文件初始化界面的内容
接上一讲,即实现下述界面的事件处理代码;并且按照配置文件初始化界面的内容(三、) 事件处理的基础知识,见下述链接五、 OPC Client第3讲(wxwidgets):wxFormBuilder;基础…...
什么是BFC,如何触发BFC,BFC有什么特性?
理解 BFC指的是块级格式化上下文,处于BFC内部的盒子与外界互不影响 触发条件 position:absolute/fixed都会产生bfcdisplay:inline-block,table,flex等float:left/right 浮动也会产生bfchtml根元素也是bfc bfc的特性 属于同一个BFC下的盒子会垂直排列属于同一个BFC下的两个…...
python做题日记(9)
第二十一题 第二十一题是合并两个有序链表,合并后的链表仍然需要保持有序,因为在合并之前已经是两个有序链表,因此在合并时只需要遍历比较两个链表中的下一结点数值,将其中较小的一个结点添加到新的列表中。如果有任何一个链表已经…...
Leetcode 3557. Find Maximum Number of Non Intersecting Substrings
Leetcode 3557. Find Maximum Number of Non Intersecting Substrings 1. 解题思路2. 代码实现 题目链接:3557. Find Maximum Number of Non Intersecting Substrings 1. 解题思路 这一题就是一个比较直接的动态规划的题目,我们只需要考察每一个位是否…...

【C++进阶篇】初识哈希
哈希表深度剖析:原理、冲突解决与C容器实战 一. 哈希1.1 哈希概念1.2 哈希思想1.3 常见的哈希函数1.3.1 直接定址法1.3.2 除留余数法1.3.3 乘法散列法(了解)1.3.4 平方取中法(了解) 1.4 哈希冲突1.4.1 冲突原因1.4.2 解…...

Spring Boot——自动配置
目录 1.bean加载方式 1.1XML方式声明bean 1.2 xml 注解方式声明bean 1.3通过Configuration和Bean 1.4使用Import注解 1.5使用上下文对象在容器初始化完毕后注入bean 1.6使用ImportSelector接口 1.7实现ImportBeanDefinitionRegistrar接口 1.8bean加载方式(…...
免费轻量便携截图 录屏 OCR 翻译四合一!提升办公效率
各位软件小达人们,今天来给大伙唠唠VeryCapture这款软件! 先说说它的核心功能。这软件有个超厉害的多模态屏幕捕捉系统,它就像个全能小能手,把截图、录屏、OCR文字识别、翻译这些功能全集成在一起啦!截图有6种模式&a…...

使用 Vuex 实现用户注册与登录功能
引言 在构建具有用户认证功能的应用时,Vuex 可以用来管理用户的登录状态和相关信息。以下是如何使用 Vuex 来实现用户注册与登录功能的概述。 🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端…...

进程通信(管道,共享内存实现)
01. 进程通信简介 进程通信工具分为数据传输工具和共享内存两类。这里我们讨论进程通信工具(IPC)里面的管道、system V和共享内存。在理解阶层通信之间,我们先了解用户空间缓冲区和内核空间缓冲区两个概念。 1.1 用户空间缓冲区 存在于用户态的进程用户空间&#…...

电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测
电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测 目录 电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测预测效果基本描述程序设计参考资料 预测效果 基本描述 电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测 运行环境Matlab2023b及以上,锂电池剩余寿…...

快速上手SHELL脚本常用命令
一、设置主机名称 1.修改文件方式 重启后生效 2.命令修改 重启shell后生效 二、网卡管理nmcli 1.查看网卡 2.设置网卡 详细配置:快速上手Linux联网管理-CSDN博客 三、简单处理字符 1.打印连续数字 2.设置字体颜色 \033[颜色代号m 3.反向打印文件内容 tac&a…...
【无标题】前端如何实现分页?
前端如何实现分页? 以下是对代码的逐条总结与解释,按 HTML、JavaScript、CSS 顺序分模块列出,每条代码单独说明: 一、HTML 代码解释 1. 表格容器 html <table class"table table-bordered table-hover">作用&…...

【自然语言处理与大模型】大模型Agent四大的组件
大模型Agent是基于大型语言模型构建的智能体,它们能够模拟独立思考过程,灵活调用各类工具,逐步达成预设目标。这类智能体的设计旨在通过感知、思考与行动三者的紧密结合来完成复杂任务。下面将从大模型大脑(LLM)、规划…...

小巧高效的目录索引生成软件
软件介绍 本文介绍的软件名为Snap2html,是一款树形目录索引生成工具。 软件大小与便捷性 Snap2html这款软件已完成汉化,其体积仅170kb,小巧无比,且无需安装,可直接投入使用。 软件使用方法 该软件操作简便…...

云原生架构设计相关原则
文章目录 前言云原生架构概述云原生架构的核心原则一切皆服务原则自动化原则韧性和容错原则可观测性原则 云原生架构原则的实践意义 前言 大家好,我是沛哥儿。今天想和大家深入探讨一下云原生架构的相关原则。在如今数字化飞速发展的时代,云原生架构已经…...
android实现使用RecyclerView详细
显示页面代码:activity_category_inventory.xml代码: <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android" xmlns:app"http://schemas.and…...

华为云Flexus+DeepSeek征文 | Flexus X实例助力 Dify-LLM 一键部署:性能跃升与成本优化的革新实践
引言 在AI大模型应用快速普及的背景下,企业对低门槛部署、高性能算力与成本可控的需求日益迫切。华为云推出的Flexus X实例,作为专为AI工作负载优化的新一代算力底座,通过1.6倍算力提升、关键业务6倍加速、综合降本30%等核心优势,…...
曼昆经济学原理第九版目录
格里高利曼昆的《经济学原理》(Principles of Economics)通常分为34章(第9版,2024年英文版),分为微观经济学(第1-18章)和宏观经济学(第19-34章)两部分 第一部…...

数据库blog7_MySql的下载与配置准备
🌿MySql下载 🍂1.应用版本选择 选择社区版,免费适合初学者 相关链接下载页面下载界面介绍 🍂2.OS版本选择 根据自己的OS类型(Windows/Linux(CentOS/Ubuntu …)/macOS)选择对应版本…...

YOLOv11助力地铁机场安检!!!一键识别刀具
文末有完整代码出处 随着现代社会的高速发展,交通工具和公共场所的安全管理面临着前所未有的挑战。尤其在机场、地铁、车站等公共安全检查点,如何提高安检效率、精准识别危险物品,成为了亟待解决的问题。在传统的安检过程中,X光图…...

RFID工业读写器的场景化应用选型指南
RFID工业读写器是上海岳冉RFID专为工业场景设计的高性能射频识别设备,核心功能围绕高效数据采集与可靠传输展开。其基础能力包括多协议支持(如ISO 18000-6C)与多标签防碰撞处理,可同时读取/写入EPC编码、用户数据等标签信息&#…...
java中的线程安全的集合
1.ConcurrentHashMap。 key,value结构。 jdk1.7通过分段锁保证不同段同时操作是线程安全的,但并发不足,jdk1.8通过node节点锁和CAS保证并发安全。不同node节点可以并发读写。通过它的computer,computerIfAbsent,等可以保证原子更新value。ifAbsent表示有…...

单片机如何快速实现查看实时数据
在用 Keil 做调试的时候,最让人头秃的是什么? 不是写代码的BUG,而是:这个条件变量是什么情况?为什么没进入这个判断?我代码跑到哪里了? 其实本质上都是通过变量判断代码的执行顺序有没有问题 …...

go实现钉钉三方登录
钉钉的的官方开发文档中只给出了java实现三方登录的,我们准备用go语言来实现 实现网页方式登录应用(登录第三方网站) - 钉钉开放平台 首先就是按照文档进行操作,备注好网站的信息 获得应用凭证,我们后面会用到 之后…...
YOLOv1 详解:单阶段目标检测算法的里程碑
在目标检测领域,YOLO(You Only Look Once)系列算法凭借其高效性和实用性,成为了行业内的明星算法。其中,YOLOv1 作为 YOLO 系列的开山之作,首次提出了单阶段目标检测的思想,彻底改变了目标检测算…...
5G 核心网切换机制全解析:XN、N2 与移动性注册对比
摘要 本文深入探讨了 5G 核心网中的三种关键切换方式:基于 XN 接口的切换、基于 N2 接口的切换以及移动性注册更新机制。通过对比分析它们的原理、应用场景和技术差异,帮助读者全面理解 5G 网络中用户移动性管理的核心技术。 1. 引言 随着 5G 技术的广泛应用,用户对网络连…...

物流配送优化实战:用遗传算法破解选址难题
在电商与供应链高速发展的今天,物流配送成本优化始终是企业竞争力的核心议题之一。想象一下,当你面对 20 个分布在不同坐标的客户点、7 个可选配送中心和 1 个发件网点时,如何用最省钱的方式完成配送?今天我们就来拆解一个真实的物…...

Linux 个人用户设置账号密码环境变量,四种方式
一、需要明白以下2点: 1、Linux 的环境变量是保存在变量 PATH 中,可通过 Linux shell 命令 echo $PATH 查看输出内容,或者直接输入 export 查看,或者输入 env 查看 2、Linux环境变量值之间是通过冒号进行隔开的( : ) 格式为&am…...

Three.js搭建小米SU7三维汽车实战(5)su7登场
汽车模型加载 我们在sktechfab上下载的汽车是glb的文件格式,所以使用gltfLoader进行加载。这里将小车直接加载进来看看效果; import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; ....其余代码省略 const gltfLoader new GLT…...
关于 SSE(Server-Sent Events)过程的简要解剖
Js前端:发送普通请求 fetch(...) .then(()>{}) .catch(()>{})Java后端:接收请求后调用请求处理函数,函数返回一个emiiter对象 public SseEmitter handleRequest(...) {// 创建一个 SseEmitter 对象,用于发送 SSE 事件SseE…...