接前面代碼內容:
OPC Client第6講(wxwidgets):Logger.h日志記錄文件(單例模式);登錄后的主界面_wx.logger-CSDN博客
OPC Client第8講:OPC UA;KEPServerEX創建OPC服務器;C#創建OPC客戶端;OpcUaHelper庫;OPC客戶端(Softing Opc Client和UaExpert)_c# opcua客戶端-CSDN博客
一、登錄后的主界面:MainFrame::InitElement()
即實現下述界面,直接看void MainFrame::InitElement()代碼及備注
?
OPC Client第3講(wxwidgets):wxFormBuilder;基礎框架;事件處理-CSDN博客
OPC Client第4講(wxwidgets):窗口布局基礎知識;界面練習_wxwidgets wxstaticbitmap-CSDN博客
OPC Client第5講(wxwidgets):實現項目的初始界面代碼-CSDN博客
OPC Client第6講(wxwidgets):初始界面的事件處理;按照配置文件初始化界面的內容_propcclient控件-CSDN博客
1、如果在.h文件中聲明了變量,.cpp中再次聲明且初始化,那么這是同一個變量嗎?
它們可以是同一個變量 —— 但前提是使用了正確的語法(如
extern
聲明),否則就可能是重復定義或鏈接錯誤。
1>聲明與定義 區別
聲明:在頭文件中,你通常會聲明變量,這意味著你告訴編譯器該變量的存在,但不分配內存空間。
定義:在源文件中,當你聲明并初始化一個變量時,你實際上是在定義它,即為它分配內存空間。
2>正確做法:加extern
或者在.cpp文件中直接初始化:g_value = 42;(對比下圖)
2、wxDataViewListCtrl:構建動態數據展示界面
wxDataViewListCtrl
提供了一種直觀且高效的方法來展示和與列表數據進行交互,非常適合用來構建動態數據展示界面。
?
3、wxTreeListCtrl:顯示層次結構數據的控件
wxTreeListCtrl是用于顯示層次結構數據的控件,它結合了 wxTreeCtrl
(樹形控件)和 wxListCtrl
(列表控件)的功能。
這個控件允許你以樹的形式展示數據,并且每個節點可以有多列信息,而不僅僅是單一的標簽。這使得 wxTreeListCtrl
成為需要展示具有多個屬性的層次化數據的理想選擇。
4、事件綁定處理??????????????????????
二、初始化準備:MainFrame::InitClient()
目的:獲取初始界面InitFrame::OnConfirm函數傳過來的配置參數config【如下圖所有的初始化信息】。
這個函數是在一、之前進入的,如下圖。
三、初始化準備1:“選擇文件(右鍵)”——C++ 讀寫 Excel :利用開源庫xlnt
二、的目的:獲取初始界面InitFrame::OnConfirm函數傳過來的配置參數config【如下圖所有的初始化信息】。
這部分是實現二、的下圖紅框部分
C++ 讀寫 Excel :利用開源庫xlnt
師傅是按照下述鏈接生成的xlnt文件夾,很奇怪。
1、利用CMake導入xlnt包
C++ 讀寫 Excel 在 vs2015 中實現(利用開源庫xlnt)_xlnt讀取中文-CSDN博客
【xlnt】入門級編譯教程_xlnt編譯-CSDN博客
按照上述鏈接的操作下載源代碼等。
再在CMake文件中導入庫,如下圖。
再用CMake重新生成
2、Vcpkg導入xlnt包【報錯放棄了】
下面自己嘗試利用Vcpkg導入xlnt包:
Vcpkg C/C++庫管理工具安裝和使用教程(鏈接VS2019)_vcpkg 安裝-CSDN博客
不知道為什么報錯(如下圖)
詢問AI排除了其它原因,提示問題如下圖
??????????????????/
下面一直顯示不出來
3、xlnt詳細操作:獲取IP.xlsx和ServerAddress.xlsx文件里的表格數據
按照下述鏈接操作就行,具體看代碼。
用XLNT庫讀寫Excel文件 | 西加加斯基
注意兩個工作簿(IP.xlsx和ServerAddress.xlsx)里都是有多張表的,如下圖
1>如何切換一個xlsx文件下不同的表格?
在 xlnt
庫中,一個 .xlsx
文件對應一個 workbook
(工作簿),而一個工作簿可以包含多個 worksheet
(工作表/表格)。
你可以通過工作表的 名稱(name) 或 索引(index) 來切換不同的表格。
2>靜態成員:類內聲明,類外初始化
3>為什么代碼中還要額外using namespace UaApp?不是已經#include<UaApp/Types.h>了嗎?
4>auto&
例如:auto& x = some_variable;
“讓編譯器自動判斷
some_variable
是什么類型,并讓x
成為它的引用(即別名)。”
四、初始化準備2:“數據庫連接配置(ODBC)”
二、的目的:獲取初始界面InitFrame::OnConfirm函數傳過來的配置參數config【如下圖所有的初始化信息】。
這部分是實現二、的下圖紅框部分
1、什么是ODBC?為什么用ODBC?
ODBC(?Open Database Connectivity):開放數據庫連接【=翻譯官】
因為我們這個暫時沒確定用哪種數據庫,所以使用的ODBC。
它是一種由微軟提出的標準數據庫訪問接口(API),目的是讓應用程序能夠以統一的方式訪問各種不同的數據庫系統,而不需要為每種數據庫編寫不同的代碼。
2、ODBC寫代碼
1>前提條件【之前已經做完了,沒有做任何其它的操作】:
- 安裝并配置好MySQL ODBC驅動(如MySQL Connector/ODBC)。
- 在“ODBC數據源管理程序”中配置一個系統DSN(數據源名稱)
ODBC 安裝/使用/編程-騰訊云開發者社區-騰訊云
- 為什么 電腦注冊表(Windows Registry)中自帶ODBC?
- ODBC作為微軟主導的跨平臺數據庫連接標準,自Windows 95起就被深度集成到操作系統中。注冊表作為Windows存儲系統配置、驅動信息、應用程序參數的核心數據庫,自然需要包含ODBC的配置項(如驅動路徑、數據源定義等),以確保系統級功能(如數據源管理器、ODBC API調用)能正常工作。
2>ODBC理解+具體的代碼寫法:
【ODBC】ODBC連接數據庫詳細說明-CSDN博客
直接看上述鏈接
句柄還看下述《3》
henv
?->?Handle?(句柄) to?Environment- 這個句柄用于管理整個ODBC環境,例如設置ODBC版本(如SQL_OV_ODBC3)。
- 通常也只需一個
hdbc
?->?Handle to?Database?Connection- 這個句柄代表應用程序與特定數據庫之間的連接。
hstmt
?->?Handle to?Statement(語句)- 這個句柄用于準備和執行SQL語句,以及處理結果集。
- 可以有多個
1》ODBC連接 Mysql 或者 Oracle 數據庫的代碼區別?
2》extern不能寫在類定義內部作為成員變量
比如在Address_handle.h里面,還會通過ODBC執行SQL語句。
extern
和 static
是語義上完全沖突的兩個關鍵字。
3》為什么ODBC的句柄要設置為全局變量?——為了復用連接、簡化調用、避免重復創建
4》數據類型轉換【自己的代碼做了改進,刪去了冗余的代碼,且正確delete了,避免了內存泄漏】
下述鏈接六、數據類型
【ODBC】ODBC連接數據庫詳細說明-CSDN博客
5》執行一條SQL語句
6》執行兩條SQL語句:先切換為同一個連接下的其它數據庫,再執行傳入的 sql 語句
【這個函數沒用上,而且寫得有問題,考慮不完全【自己已經改好】】
切換數據庫的關鍵是——構造一個像 "USE your_database_name;"
這樣的完整 SQL 語句字符串,然后用 SQLExecDirect
去執行它。
?五、初始化準備3:“緩沖區設置”【DataBuffer.h】
二、的目的:獲取初始界面InitFrame::OnConfirm函數傳過來的配置參數config【如下圖所有的初始化信息】。
這部分是實現二、的下圖紅框部分
- 大小 (Size, 條):指緩沖區能容納的最大數據條目數量。達到此上限時,可能需要丟棄舊數據或阻塞寫入。
- 存儲閾值 (Threshold, 條):指觸發緩沖區刷新(如寫入磁盤、發送)所需積累的數據條目數量。達到此數量時,立即處理緩沖區內容。
- 存儲周期 (Storage Period, 秒):指緩沖區中數據的最長保留時間。超過這個時間的數據應該被“過期”或觸發處理(如寫入文件、發送網絡)。
1、std::stoull
std::stoull:
字面意思就是 "string to unsigned long long"(字符串轉無符號長長整型)
2、函數的參數為什么是size_t
類型的?
1>size_t區別1、的unsigned long long
2>size_t
是一個無符號整數類型(通常是 unsigned int
或 unsigned long
),它被設計用來表示:
- 對象的大小(例如?
sizeof
?的返回值) - 容器的大小(例如?
std::vector::size()
) - 數組的索引
- 內存相關的計數
它的核心語義是:“非負的、用于表示大小或數量的整數”。
3>為什么?setProcessingThreshold
?和?setMaxBufferSize
?用?size_t
?是合理的?
processingThreshold
: 表示“多少條”數據觸發存儲。這是一個數量,必須是非負整數。size_t
?完美匹配其語義。maxBufferSize
: 表示緩沖區能容納的“最大條數”或“字節數”。這也是一個大小/容量,size_t
?非常合適。
4>師傅的代碼有問題:為什么?setbufferTimed
?用?size_t
?是不合理的?
bufferTime
: 表示“時間間隔(秒)”。- 問題1:精度丟失:時間間隔通常需要小數。例如,你可能希望輪詢間隔是?
0.5
?秒、1.2
?秒或?0.1
?秒。size_t
?只能存儲整數,setbufferTimed(0.5)
?會被截斷為?0
,導致輪詢間隔為0秒,這幾乎等同于忙等待(busy-waiting),會耗盡CPU資源,是嚴重的性能問題。 - 問題2:語義不匹配:雖然時間間隔是一個“量”,但它本質上是一個物理量(時間),而不是一個“數量”或“大小”。
size_t
?的語義是“大小/數量”,而時間間隔的語義是“持續時間”。 - 問題3:靈活性差:無法設置亞秒級(sub-second)的輪詢間隔,這在需要高響應速度的系統中是致命的。