教程2:創建您自己的應用
請跟隨本教程學習TouchGFX的更多基本知識。 您將學習如何將圖像添加到應用以及如何使用按鈕。 您還將學習如何使用文字和計算數字。 在最後的步驟中,您將編寫程式碼,以便增強使用TouchGFX Designer創建的UI的視覺效果。 本教程假設您沒有TouchGFX的相關知識,但是有一點程式設計的經驗。
第1步:設置背景圖像
在第一個步驟中,您將看到如何插入PNG圖像作為背景。 但首先我們將新建一個專案。
新建一個專案
在TouchGFX Designer中啟動新專案。 我們將該專案命名為“MyApplication1”。 該專案基於“STM32F746G探索套件”。
如果您有其他STM32評估套件,請查看TouchGFX Designer提供的支援的設備清單中是否包含此套件。 如果您沒有支援的開發板,可以選擇“Simulator”,並直接在Windows電腦上運行應用。
請注意,本教程在解析度為480x272的顯示器上運行。 如果您選擇具有其他解析度的應用範本,則圖形與螢幕將不匹配,儘管如此,您仍應能夠完成本教程。
現在,有一個新建的空白專案,我們開始修改它。
TouchGFX應用包含許多螢幕。 螢幕包含許多小部件,它們共同構成了使用者介面。 螢幕覆蓋整個顯示器,因此一次只能向使用者顯示一個螢幕。
首先要做的是將初始螢幕的名稱修改為“Main”,如下圖所示。 在左側清單中選擇該螢幕 (1),並在右側的名稱欄位中修改名稱 (2)。 也可通過按兩下或按右鍵清單的螢幕 (1) 來重命名螢幕。
插入背景
用一個或多個小部件覆蓋螢幕的整個背景通常是個不錯的選擇。 例如,可以是方塊或圖像。 如果不覆蓋,背景將顯示為黑色。 在本應用中,我們將使用圖像。
我們需要匯入檔案,然後才能在TouchGFX Designer中使用圖像。 TouchGFX支援BMP和PNG圖像(儘管TouchGFX Designer只支援匯入PNG圖像)。 PNG檔優先於BMP檔,原因是前者更小且支援透明像素。
本教程將使用的圖像可從此連結下載。 將檔案解壓縮到硬碟上的目錄。
我們想要使用名為“background.png”的檔作為背景。 為了匯入該文件:
- 選擇“Images ”選項卡並點擊“+”按鈕。
- 選取到解壓縮檔夾並選擇“background.png”文件。
- 按下“打開”按鈕匯入檔案。
為了將檔案匯入專案,您還可以將檔案瀏覽器中的圖像拖放到“圖像”選項卡上,甚至直接拖放到畫布上。
請注意,導入專案的圖像會被轉換並編譯到專案中,因此會佔用快閃記憶體空間。 請只匯入需要的圖像。 為了添加圖像,點擊左側的“Images”按鈕 (1),然後點擊右側的“+”按鈕 (2)。 TouchGFX Designer打開普通的檔案瀏覽器,在這裡您可以選取到下載的圖像並選擇“background.png”文件。
現在,我們可以在應用中使用該圖像。 為此,我們需要一個圖像小部件。
- 點擊左側的“Canvas”按鈕 (1)
- 在小部件清單中找到圖像小部件 (2)
- 點擊它在螢幕上插入圖像小部件。
最好為小部件改一個有意義的名稱。 在本例中,我們使用“backgroundImage”(3)。
在插入小部件後,通常需要配置它的一些屬性,如位置和顏色。 在TouchGFX Designer中,所選小部件的屬性顯示在右側。 螢幕中的小部件顯示在左側的樹狀檢視中 (1)。 在本例中,我們對點 0,0 所在的位置感到滿意,但想要修改圖像屬性,以便選擇之前匯入的檔案“background.png”。 點擊圖像屬性 (2) 並選擇“background.png”。
現在,我們已經創建了一個簡單的應用,它有一個包含一張覆蓋了整個使用者螢幕的背景圖像的螢幕。
在繼續操作前,嘗試按下“Run Simulator”按鈕,以便確認專案正常編譯和運行。 由於尚未添加任何活動的小部件,因此現在還不能與應用通訊。
第2步:添加按鈕
在這一步中,我們將為應用添加兩個按鈕,並用不同的PNG檔給予它們自訂外觀。
添加按鈕
- 為了將按鈕添加到螢幕,點擊“widget”選項卡上的按鈕小部件 (1)。
- 用滑鼠拖曳新的小部件以便移動它。
- 將按鈕定位在位置 (x=40, y=60) 處。 檢查右側屬性中的位置 (2)。
- 將新的小部件命名為“buttonUp”。
- 在位置 x=40, y=150 處添加另一個按鈕。 將此小部件命名為“buttonDown”。
現在,專案如下圖所示:
您可以使用X和Y屬性的向上/向下小按鈕對小部件的位置進行微調。 您也可以選中按鈕小部件(在畫布上點擊它),然後用鍵盤上的方向鍵調整位置。
修改外觀
現在,我們將修改按鈕的外觀。 按鈕由兩幅圖像構成。 一幅圖像在按鈕被按下時顯示,另一幅圖像在按鈕未被按下(釋放)時顯示。 大多數小部件都附帶一組預定義樣式,實際上是描述小部件具體外觀的一組特定屬性值。 這些樣式有助於進行快速的原型開發,但在創建實際應用時,通常會將它們替換掉。
像上一步一樣轉至“Images”選項卡,並點擊右上角的“+”圖示匯入一些圖像。 此次導入四張圖像:"button_down_pressed.png", "button_down_released.png", "button_up_pressed.png", and "button_up_released.png"。
可以看到,雖然我們只匯入了5張圖像,但專案中共有7張圖像。 另外兩張是按鈕上預設使用的藍色圖像。 當不再使用時,這些圖像會被自動刪除。
回到畫布並選擇“buttonUp”按鈕。 點擊“Released Image”屬性 (1),然後點擊“Project”顯示圖像 (2),最後選擇正確的圖像 (3)。 對於“buttonUp”,為“釋放圖像”屬性選擇“button_up_released.png”。 為“按下圖像”屬性選擇“button_up_pressed.png”。
您可以立即看到TouchGFX Designer中畫布上按鈕的外觀。
對於“buttonDown”,為釋放圖像選擇“button_down_released.png”,為按下圖像選擇“button_down_pressed.png”。
現在,您已完成按鈕的設置。 點擊“Run Simulator”嘗試運行應用。
嘗試使用兩個按鈕,以便確認按鈕配置正確。
Tip
第3步:添加文字
在這一步中,我們將為應用添加一個大尺寸的TextArea工具。
所有文字均通過TextArea工具來顯示,但在將TextArea添加到應用之前,我們先添加另一張圖像,以便為文字提供一個更好的背景。
文字背景
- 匯入另一個影像檔“counter_box.png”。
- 插入新的圖像小部件
- 將其命名為“textBackground”
- 將其定位在位置 (x=250, y=59) 處。
- 將圖像屬性設置為“counter_box”。
添加文字
現在,我們可以添加TextArea小部件。 點擊“小部件/其他”下拉式功能表中的TextArea圖示。 將小部件重命名為“textCounter”,並將小部件移動到位置 (x=250, y=90) 處。 我們要讓小部件顯示大文字,因此取消選中 Auto-size屬性,並將尺寸設置為固定寬度=152和高度=90。
TextArea小部件的默認色彩是黑色,在背景上顯得很暗。 選擇“textCounter”的Color屬性,將顏色修改為白色。
修改文字字體排印
我們要讓文字更大。 為此,需修改文字使用的“字體排印”。 字體排印定義了文字的“字體”(如Verdana)、“尺寸”和“對齊”(左、右或中心)。
選擇TouchGFX Designer左上角的“Texts”選項卡 (1),點擊“Typographies”(2),並將“Default”字體排印的大小更新為80 (3)。
回到螢幕(點擊左上角的“Canvas”選項卡),現在我們可以看到文字大了許多。 事實上,我們無法讀取完整的文字“New Text”。 點擊Alignment屬性下的中心對齊圖示讓文字中心對齊 (1)。
使用萬用字元文字
我們要讓TextArea顯示一個可以用按鈕修改的數字。 為此,我們必須修改文字,以便包含“萬用字元”。 萬用字元是文字中的一種標記(“<d>”),在運行時可以用其他一些字元(如數位)代替。 我們只想顯示一個數位,因此將文字修改為簡單的“<d>”。 在其他專案中,您可以將動態部分與固定文字進行組合,如“溫度:<temp> °C"。
Note
將文字修改為“<d>”(1),點擊“Wildcard 1”(2),將預設值設置為“0”,並選中“Use wildcard buffer”。
點擊“Run Simulator”嘗試運行應用。
Further reading
第4步:添加程式碼
使用TouchGFX Designer時,可輕鬆地通過交互將操作連結到按鈕。 交互將觸發條件(如按鈕按下)連結到操作(如運行程式碼或移動元素)。
選擇右上角的“Interactions ”選項卡 (1),點擊“+”按鈕新建交互。
我們將創建兩個交互,每個按鈕一個。 我們將兩個交互都設置用來在當前螢幕上呼叫C++方法。
- 將“Trigger”屬性修改為“Button is clicked”。
- 將“Choose clicked source”屬性設置為“buttonUp”。
- 將“Action”屬性修改為“呼叫新的虛擬函數”。
- 在“Function Name”欄位鍵入“buttonUpClicked”。
- 您還應為交互取一個描述性的名稱,以方便日後識別。
用“buttonDown”創建相似交互“clicked source”:
- 點擊“+”啟動新的交互。
- 將“Trigger”屬性修改為“Button is clicked”。
- 將Choose clicked source屬性設置為“buttonDown”。
- 將“Action”屬性修改為“呼叫新的虛擬函數”。
- 對於Function Name,輸入"buttonDownClicked"。
- 您還應為交互取一個描述性的名稱,以方便日後識別。
如果您點擊“生成程式碼”按鈕或“運行模擬器”按鈕,TouchGFX Designer將用您在剛創建的交互中輸入的資訊更新生成的程式碼。 這意味著它將在View基類中為該螢幕創建兩個新的虛擬函數。
我們進一步研究要如何執行自己的程式碼。 點擊右下角的“Generate Code”按鈕,然後點擊左下角的“Files”按鈕。 打開的文件瀏覽器並選到在應用程式資料夾。 選取到以下資料夾:
MyApplication1/TouchGFX/generated/gui_generated/include/gui_generated/main_screen/
並打開文件MainViewBase.hpp。 如果您願意,還可以打開一個專案檔案並在IDE中找到該檔案:
IDE | 專案檔案路徑 |
---|---|
STM32CubeIDE | MyApplication1/STM32CubeIDE/.project |
Visual Studio | MyApplication1/TouchGFX/simulator/msvs/Application.sln |
IAR Embedded Workbench 8 | MyApplication1/EWARM/Project.eww |
KEIL uVision v5 | MyApplication1/MDK-ARM/STM32F746G_DISCO.uvprojx |
Note
新的虛擬函數位於MainViewBase
類的公開部分。 生成的方法具有空實現。 用意是程式師在子類MainView
中實現這些方法。
MainViewBase.hpp
/*********************************************************************************/
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
/*********************************************************************************/
#ifndef MAINVIEWBASE_HPP
#define MAINVIEWBASE_HPP
#include <gui/common/FrontendApplication.hpp>
#include <mvp/View.hpp>
#include <gui/main_screen/MainPresenter.hpp>
#include <touchgfx/widgets/Image.hpp>
#include <touchgfx/widgets/Button.hpp>
#include <touchgfx/widgets/TextAreaWithWildcard.hpp>
class MainViewBase : public touchgfx::View<MainPresenter>
{
public:
MainViewBase();
virtual ~MainViewBase() {}
virtual void setupScreen();
/*
* Custom Action Handlers
*/
virtual void buttonUpClicked()
{
// Override and implement this function in MainView
}
virtual void buttonDownClicked()
{
// Override and implement this function in MainView
}
...
實現虛擬函數
現在剩下的任務是實現這兩種方法,以便在使用者按下按鈕時修改計數器的值。 為此,在MainView
類中再次宣告方法。 這個類能在以下路徑中找到:
MyApplication1/TouchGFX/gui/include/gui/main_screen/MainView.hpp
打開此文件,並在類中插入兩個函式宣告:
MainView.hpp
#ifndef MAIN_VIEW_HPP
#define MAIN_VIEW_HPP
#include <gui_generated/main_screen/MainViewBase.hpp>
#include <gui/main_screen/MainPresenter.hpp>
class MainView : public MainViewBase
{
public:
MainView();
virtual ~MainView() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void buttonUpClicked();
virtual void buttonDownClicked();
}
下一個任務是在.cpp檔中添加實現,以便實現兩種方法。 此檔的位置:
MyApplication1/gui/src/main_screen/MainView.cpp
在下面的實現中,我們將呼叫添加到touchgfx_printf
。 此函數用於在運行模擬器時印出文字。 為了使用此函數,需要包含檔案utils.hpp。 在目標上運行時,文字行無效。
MainView.cpp
#include <gui/main_screen/MainView.hpp>
#include <touchgfx/utils.hpp>
MainView::MainView()
{
}
void MainView::setupScreen()
{
MainViewBase::setupScreen();
}
void MainView::tearDownScreen()
{
MainViewBase::tearDownScreen();
}
void MainView::buttonUpClicked()
{
touchgfx_printf("buttonUpClicked\n");
}
void MainView::buttonDownClicked()
{
touchgfx_printf("buttonDownClicked\n");
}
在TouchGFX Designer中再次點擊“Run Simulator”運行新程式碼。 多次點擊按鈕,確認交互和方法的運作符合預期:
更新計數器值
最後一個任務是在新方法中寫入C++程式碼,以便在使用者按下按鈕時更新計數器值。 為此,我們首先在MainView
類中添加新的整數變數counter
:
MainView.hpp
#ifndef MAIN_VIEW_HPP
#define MAIN_VIEW_HPP
#include <gui_generated/main_screen/MainViewBase.hpp>
#include <gui/main_screen/MainPresenter.hpp>
class MainView : public MainViewBase
{
public:
MainView();
virtual ~MainView() {}
virtual void setupScreen();
virtual void tearDownScreen();
virtual void buttonUpClicked();
virtual void buttonDownClicked();
protected:
int counter;
}
在buttonUpClicked
方法中使計數器值遞增: 新的值隨後被轉換為字串並複製到我們在上一步中為TextArea配置的萬用字元緩衝區:
MainView.cpp
#include <gui/main_screen/MainView.hpp>
MainView::MainView()
{
}
void MainView::setupScreen()
{
MainViewBase::setupScreen();
}
void MainView::tearDownScreen()
{
MainViewBase::tearDownScreen();
}
void MainView::buttonUpClicked()
{
touchgfx_printf("buttonUpClicked\n");
counter++;
Unicode::snprintf(textCounterBuffer, TEXTCOUNTER_SIZE, "%d", counter);
// Invalidate text area, which will result in it being redrawn in next tick.
textCounter.invalidate();
}
void MainView::buttonDownClicked()
{
touchgfx_printf("buttonDownClicked\n");
counter--;
Unicode::snprintf(textCounterBuffer, TEXTCOUNTER_SIZE, "%d", counter);
// Invalidate text area, which will result in it being redrawn in next tick.
textCounter.invalidate();
}
TextArea小部件使用Unicode,因此我們必須使用支援寫入Unicode緩衝區的特殊snprintf函數。
請注意,我們會在更新後在textCounter
小部件上呼叫 invalidate()
。 如此可確保在計數器值更新後重繪TextArea。
在應用完成前,還需要做一件事。 TouchGFX只包含需要的字元,因此需告知TouchGFX Designer在“Default”字體排印中包含字元0-9。 為此,返回TouchGFX Designer並點擊“Texts”選項卡,然後點擊“Typographies”選項卡。 在“Default ”字體排印的“Wildcard Ranges”列中添加範圍“0-9”(1)。
現在,再次點擊“Run Simulator”,然後點擊幾次“向上”按鈕:
程式現在還不能正確地處理負數。 為了解決這個問題,可在buttonDownClicked()
函數中插入guard以確保計數器值不會小於0,或者將字元“-”添加到使用的字體排印。 為此,只需在“Default”字體排印的“Wildcard Characters”儲存格中添加負號(“-”)即可。
教程2到此結束。