Linux C++/Qt 基础编程内容较多,为方便阅读,Qt部分拆出来一章。Qt Widget 和 Qt Quick 是 Qt 中两套完全不同的 UI 技术栈,设计目标、使用方式和适用场景都有明显差异。其中可视化读取设置PWM值和TXT文本读写使用widget实现。JSON文件读取显示使用quick架构实现。现在就可以将程序编译上传到开发板看一下效果,只是一个空白的窗体。1,窗体大小与屏幕一致1280*720,并且全屏显示设定PWM控制转速的实现与C++一致,把代码抄过来。然后在旋钮改变值的函数中调用这个函数,设置PWM。编译上传,在屏幕滑动旋钮改变数值,查看log和风扇转速。 txt文本浏览器是把C++编程中的txt文件读写程序做成可视化软件的升级。软件框架继续使用widget。 项目继续使用可视化PWM控制的工程,只是添加一个ui,由c++选择加载显示。创建完成后是默认大小和样式。我们把它改成我们想要的样子。再把在cpp_practice中读txt的代码拷贝过来:我们使用ls命令把输出直接写入一个aaaa.txt文件6,点击保存后,到命令行中使用cat查看修改后的内容:------------------------------------------------------------------------ 上面两个GUI程序都是widget架构,接下来读取显示JSON的程序我们将使用quick架构。创建项目:最新的Qt Creator是基于Qt6的,我们用的是Qt5,所以要用旧版本的Qt Creator创建 quick项目以支持Qt5.项目创建后,关闭这个旧版本的Qt Creator即可。然后到文件中删除配置。QML也有可视化设计界面,但是几乎没人用,不如写代码实现。不信的自己试试,我就不陪你试了。在QML界面程序开发当中,MVC架构格外明显。这里在设计页面之前先对MVC架构进行介绍。这个项目中读取的JSON数据就是model,qml及加载qml的类属于view,model读取JSON数据传递给view进行更新显示,中间传话的就是controller。作为一个中间人,他既要能够跟model部分进行C++交互,又要能够跟qml交互。我们有两种方式创建这样的一个角色,一是注册类,二是注册类型。而且这个注册动作必须在qml页面加载之前进行。qmlRegisterType<T>() —— 把 C++ 类注册成 QML 里可实例化的类型,QML 侧能 MyType { … }随便 new。
qmlRegisterSingletonType<T>() —— 把 C++ 类注册成 QML 单例,全局唯一定义,QML 侧直接 MySingleton.xxx访问,不能 new。
添加类后,在类中添加一个函数和一个信号。函数必须用Q_INVOKABLE来修饰,这样QML中才能调用。而且这个函数必须在对应cpp中有实现。这样的类才可以注册到QML环境中,下面在main.cpp中注册这个类的类型到QML上下文中。这样注册类型后便可以在QML中使用,但是需要先import :在QML中调用方法和接受信号,函数不在这里调用,只是演示:再演示 qmlRegisterSingletonType 注册上下文句柄的方式添加类的方式与qmlRegisterType相同。这个类起名:Singleton_js_ctl。然后在main.cpp中使用qmlRegisterSingletonType 注册类型。文件选择使用我司提供的 MyFileDialog.qml 实现现在我们准备一个JSON文件,打开并格式化读取输出它。写一个JSON文件,包含root节点,然后是people节点,每个people节点有身高体重性别属性。不要过度解释。{ "root": { "people": [ { "height": 175, "weight": 70, "gender": "male" }, { "height": 165, "weight": 55, "gender": "female" }, { "height": 180, "weight": 75, "gender": "male" } ] }}
上面是生成的JSON文件内容,我们把它保存到本地的一个JSON文件中:jsontest.json 。然后继续问AI,让它帮们写一段格式化读json的程序然后再linux系统重使用C++语言和CJSON库读取这个JSON文件,把每个人的属性存在一个结构体当中,结构体存在vector当中。
在 Singleton_js_ctl 中添加一个 void readjson(QString path); 函数实现这个功能。# 禁用cJSON的Config模式set(cjson_FOUND TRUE)# 手动设置set(CJSON_INCLUDE_DIRS /qirou_tools/aarch64-linux-gnu_t527sdk/aarch64-buildroot-linux-gnu/sysroot/usr/include/cjson)set(CJSON_LIBRARIES /qirou_tools/aarch64-linux-gnu_t527sdk/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libcjson.so)include_directories(${CJSON_INCLUDE_DIRS})target_link_libraries(your_target_name ${CJSON_LIBRARIES})
voidSingleton_js_ctl::readjson(QString path){ std::ifstream file(path.toLocal8Bit ().data ()); if (!file.is_open()) { std::cerr << "Failed to open file" << path.toLocal8Bit ().data () << std::endl; return; } std::string content((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>()); file.close(); cJSON *root = cJSON_Parse(content.c_str()); if (!root) { std::cerr << "JSON parse error" << std::endl; return; } cJSON *peopleArray = cJSON_GetObjectItem(root, "root"); peopleArray = cJSON_GetObjectItem(peopleArray, "people"); std::vector<Person> persons; cJSON *item = nullptr; cJSON_ArrayForEach(item, peopleArray) { Person p; cJSON *height = cJSON_GetObjectItem(item, "height"); cJSON *weight = cJSON_GetObjectItem(item, "weight"); cJSON *gender = cJSON_GetObjectItem(item, "gender"); p.height = height->valueint; p.weight = weight->valueint; strncpy(p.gender, gender->valuestring, sizeof(p.gender) - 1); p.gender[sizeof(p.gender) - 1] = '\0'; persons.push_back(p); } cJSON_Delete(root); // 验证输出 for (const auto &p : persons) { std::cout << "Height: " << p.height << ", Weight: " << p.weight << ", Gender: " << p.gender << std::endl; }}
QML接受ctroller信号,页面显示格式化读取的json内容。