尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从零通过AI实现TouchGFX的界面交互(二):Image按钮、ClickListener、Wildcard动态数据与Screen切换

从零通过AI实现TouchGFX的界面交互(二):Image按钮、ClickListener、Wildcard动态数据与Screen切换 本文环境MCUSTM32H743LCD1024×600 RGBGUITouchGFXFramebuffer外部 SDRAM图片资源QSPI FlashRTOSFreeRTOS当前已经完成 LCD 点亮与触摸移植实现界面的交互在能够点亮屏幕后证明我们的整个函数逻辑架构以及硬件都是没有任何问题现在我们可开始实现简易的可交互界面接下来将分享我的整个交互界面设计过程相比于学习内容我们此次完全专注于实现整个可交互的界面其余事情我将全部交给AI并展示整个工作流程。一、插入图片在本文这个项目中为了快速做出视觉统一的界面我们将大量采用图片与点击的方式实现自定义控件因此从表现层看大部分按钮和背景都由位图资源组成所以我们甚至可以这么理解在touchGFX中插入很多张图片就可以了。有些图片作为背景有些图片作为按钮有的可以点击有的不能点击当检测到点击后我们就做出一些操作反之则不做出操作。操作菜单如下由于我们先简易入门此次只提及第一个和第二个功能而这两个操作最大的区别在于第二个添加的图片可以进行缩放和调整。添加一张背景图因此我们可以先尝试使用第一个普通的Image功能添加一张图片点击No image从本地添加第一张图片同时记得一定要给图片添加名称这在之后非常重要这时候你将会添加第一个你的本地文件。但是我们又遇到了一个麻烦目前我们单片机使用的是1024*600的分辨率我上哪找这样的图片呢我是否应该使用第二个功能去放置一张可以缩放的图片呢先说结果作为初学者我们最好不要使用第二个可缩放图片功能。假设添加的一张普通网图那么这张图片的分辨率大概率高于1024*600你再缩小适应后将其放进去第一会增加内部的处理压力第二这张图片在屏幕上显示时会经过额外处理增大当前芯片压力。普通 Image 可以直接根据 Bitmap 像素文件直接通过像素进行绘制而 Scalable Image 在每次重绘时还需要执行像素坐标映射和插值计算因此 MCU 负载明显更高。对于 1024×600 这种固定界面最好在 PC 或 AI 图像工具中提前将素材处理为目标分辨率再作为普通 Image 导入像素文件而且由于屏幕的限制最后的显示的还是1024*600的图片因此我们最好的办法则是使用我们的桌面AI软件让其帮我们进行处理并生成合适的图片就可以了。生成完毕后继续添加图片然后我们会发现添加图片之后整张图片图片直接就完整平铺在框架内同时这张图片也会被添加到资源库中进行存储最后一同下载进单片机flash当中。内部图片资源我们还可以看到这个图片的部分信息和存储位置有些部分不能修改比如图片格式等等但是我们可以修改是否存在内部flash还是外部ext flash中。有些芯片类似于H750系列等等内部flash较小只能存储在外部flash当中。因此如果不注意的话就会出现报错或者不显示的现象所以建议这些图片资源统一存储外部flash或者使用H743这类内部flash较大的芯片。为什么经常需要外部 FlashTouchGFX 的对flash的需求通常不是代码而是 Bitmap、字体等图形资源。一张 1024×600 RGB565 像素数据可以达到1024 × 600 × 2 ≈ 1.17 MiB因此对于内部 Flash 容量有限的 MCU大量 UI 素材通常需要放入 QSPI/OSPI Flash。帧缓冲则通常放在 SDRAM 中两者用途并不相同。以上就是我们插入一张图片的完整流程这时候我们点击下边的Run Simulator就可以生成相应代码下载程序后应该可以如期点亮屏幕。将图片变成可交互按键现在进入下面一个部分我们之前说几乎所有功能和操作说通俗一点都是在围绕图片去执行因此按键也不例外。我们可以尝试添加touchGFX的官方按键使用非常的简单而且按下去会有动画反应。但是官方的库过于单调我们要是想自己做应该怎么办呢我们还是使用图片功能我们看看之前没有标注的部分假如我们勾选了第二个ClickListener那么touchGFX就会生成相应的回调函数而我们通过读取这个回调函数就可以知道点击的状态与坐标等等至于之后再实现什么操作就交给AI即可大家感兴趣可以自行查阅。启用该功能后TouchGFX 会改变这个控件生成时的声明方式在原本的 Image 控件外增加 ClickListener使这个图片具备接收触摸事件并触发回调的能力touchgfx::ClickListenertouchgfx::Image startImage;触摸事件进入处理函数后可以判断是哪个图片产生了事件再执行对应操作void MainView::imageClickHandler( const touchgfx::Image image, const touchgfx::ClickEvent event) { if (image startImage) { // 开始操作 } }下面展示完整流程首先通过AI软件生成四个按钮图片同时一样要记得生成合适分辨率的图片。此时当我们按下时图片颜色变深松开时便会切换为另一种状态有一个不错的交互效果然后对这四个图片进行命名同时勾选刚刚提到的ClickListener然后输入合适的提示词让AI去完成相应的切换逻辑同时我们一定要注意的是这些 vibe coding 软件肯定是读取现有的文件你一定要先导入图片将图片重叠放置在同一位置后记得通过命名区分图片因为你还需要向AI阐述你想要的实现逻辑点击 Run Simulator 且成功后才能进行到下一步。因为只有Run Simulator成功后你刚刚的图形化配置才真正变成代码与文件你的项目才算一次更新。提示词与操作效果如下同样先点击仿真生成相应代码然后在仿真界面测试成功后下载程序基本就可以了。生成代码失败问题再不断的尝试中我们肯定会遇到Run Simulator 失败的情况其实大部分时候很好理解比如当我们让 AI 去把其中一个模块逻辑和另一个模块逻辑联系到一起这时当我们在touchGFX的图形界面删掉这个模块时这部分的模块代码消失了但实现逻辑调度的代码并未消失这时就会出现报错我们需要让AI找出报错位置删除这一部分逻辑即可二、实时动态数据显示在之后的应用中我们会发现又有一个难题我如何让这个屏幕显示实时数据呢这时我们就需要使用里面的文本框功能通过touchGFX中的文本框功能实现文字的写入。动态占位符但是这个时候假如我跟AI说去不断改变这个文本框的数字根据 xxx 地方的数值AI是无法在仅修改用户代码的情况下做规范修改的。这时候我们需要使用wildcard动态占位符这个功能因为TouchGFX 不允许直接把整数变量塞进普通静态文本里所以我们需要额外留出一个地方用于动态变化。同时我们需要为当前文本框提供字库假如我们需要显示一个数字8数字8的编码已经写进 buffer但屏幕要真正画出8还需要字体资源中存在数字8的像素字形。如果没有准备这个字形就可能显示成 之类有没有人遇到过这样的问题呢字库​​​​我们还需要在字符库里面输入我们需要显示的所有数字以便之后调用不会出现乱码。同时多个文本框可以调用同一个字符库因此我们也可以写的完善一点。不断更新 Buffer 中保存的字符Unicode::snprintf( progressDisplayBuffer, PROGRESSDISPLAY_SIZE, %d, progressValue ); progressDisplay.invalidate();在实现了动态占位符以及数字库之后我们就可以使用AI进行调用了逻辑严谨表达诉求让AI用相应代码即可实现。调试插曲通过我写的提示词大家还可以发现在这个动态显示的过程中我的显示出现了频繁闪烁最后经过尝试发现是由于两个问题导致1.我一开始图方便像第一节中说的使用了高清图片进行缩放的背景大大加大了我图形显示的缓存压力2.这里的现象也可能与 SDRAM 带宽、LTDC 取数、重绘面积以及运行时图片缩放共同有关。虽然当时配置的时候数据手册建议值是50MHz左右但是经过使用最后将LTDC外设时钟降至40MHz至此屏闪问题解决。三、了解基本交互逻辑现在我们已经学会了 TouchGFX 中常用的一些模块但是我们如何进行管理以及调整呢这时需要我们了解TouchGFX这个图形化界面的交互逻辑以及编辑方式。界面分类假设我们想做一个特别复杂的菜单我们在一个界面中放入多张背景图。跟AI说点击这个按钮时显示这个点击那个按钮时显示另一个但是界面中的元素越来越多即使AI很难出错我们人都要看糊涂了。这时候我们需要将界面进行分类添加新的界面。即使现有的界面一样但是里面的按钮不同实现的功能不同我们也需要进行分类同时以便其它人可以一眼就看出你的整个交互规划。这里我使用了多个screen每个screen里面放了多个不同模块点击按钮也可以实现不同screen之间的跳转内容清晰分类明了同时更方便于命名界面中的各种元素显示层级关系同时值得注意的是每个screen界面下的元素排列顺序就代表这个元素所处在的层级如果发现背景将文件盖住了那么就将对应名称的元素拖至上层就会浮现出来容器与控件我们通过每个大的界面实现大的分类那我要想统一调动一些小的元素模块应该怎么办呢这时我们就需要使用TouchGFX为我们提供的容器这个功能可以用于元素的分类以及一些简易动画的实现功能很强大目前我也没有了解全不过我们只需要先掌握普通容器的使用即可容器与控件如下图所示假如我因为界面空间不够想在一个空间完成两种不同小界面的切换最方便的办法是什么呢就是将其添加至容器当中。这样我就可以实现同时隐藏或者显示一个容器中的全部元素或者模块省去了一些繁杂的操作大家感兴趣可以进行尝试。说明这里我们暂时可以把 Screen 简单理解为 TouchGFX 中的一个完整页面不过从程序结构上来说一个 Screen 并不仅仅是 Designer 中看到的一张画布。当我们创建一个新的 Screen 后TouchGFX 还会为这个页面生成对应的 View显示控制 和 Presenter 逻辑控制。文件架构​​​​​​其中View 主要负责界面的显示例如页面中的图片、按钮、TextArea 等控件都属于 View 管理的内容而 Presenter 则更接近这一页面的逻辑层用于处理与其它外设或交互之间的逻辑控制。除此之外TouchGFX 整个应用还存在一个公共的 Model。Model 可以用于保存需要跨页面存在的状态同时也是 TouchGFX 界面与 STM32 后台程序之间进行数据交互的重要接口。因此可以暂时将 TouchGFX 的数据关系简单理解为STM32后台程序→ Model → Presenter → View →屏幕显示而当用户在屏幕上进行操作时则可以反过来用户操作→ View → Presenter → Model →STM32后台程序我们的项目后续已经将 ADC、传感器或串口接收到的真实数据实时显示到界面中时就逐渐用到这一套结构比如本文的超声波电源设计之后有时间会进一步完善这个内容。
返回列表