#申请原创#
上次我们领略了Wio终端在显示字体方面的多样性,并为其添加汉字显示功能,本次我们介绍一下显示控件的效果设计及其程序实现,从而增强界面的表现力。 自Windows操作系统面世以来,大家以习惯了它的界面操作风格,在基于单片机及ARM所设计的系统上,也可以仿照它的风格来设计界面,其中主要的工作就是设计相应显示控件。
1.控件制作 在Windows系统下,常用的显示控件包括按键、单选、多选、文本框、选项卡、下拉菜单、下拉列表等。 在介绍控件在Wio终端的实现方法前,先做的准备工作就是构建一个用于实验的小中文字库,其作用大家会在后面体会到。 该字库的内容如下: unsigned char Hzk[]={ 0x04,0x43,0x30,0x01,0x20,0x25,0x25,0xFD,0x25,0x25,0x20,0x10,0x21,0xC6,0x00,0x00, 0x20,0x20,0x7E,0x80,0x02,0xF3,0x2A,0x22,0x2C,0xF4,0x05,0x82,0x04,0x18,0x60,0x00,/*"澎",0*/ 0x08,0x06,0x40,0x31,0x00,0x11,0x11,0xFF,0x11,0x11,0x00,0x7F,0x44,0x44,0x7F,0x00, 0x20,0x20,0x7E,0x80,0x00,0xF8,0x10,0x10,0x10,0xF9,0x06,0xF8,0x42,0x41,0xFE,0x00,/*"湖",1*/ 0x08,0x06,0x40,0x31,0x24,0x29,0x21,0xBD,0x61,0x21,0x3D,0x21,0x28,0x24,0x00,0x00, 0x20,0x20,0x7E,0x80,0x00,0x70,0x50,0x50,0x50,0x52,0x51,0xD2,0x1C,0x00,0x00,0x00,/*"湾",2*/ 0x00,0x3F,0x20,0x20,0x3F,0x01,0x11,0x11,0x11,0xFF,0x11,0x11,0x11,0x11,0x01,0x00, 0x00,0xF0,0x20,0x20,0xF4,0x08,0x10,0x60,0x80,0xFF,0x80,0x60,0x10,0x08,0x04,0x00,/*"味",3*/ 0x02,0x02,0x42,0x33,0x00,0x10,0x97,0x55,0x1D,0x15,0x15,0x55,0x97,0x10,0x00,0x00, 0x00,0x02,0x04,0xF8,0x04,0x02,0xFA,0x52,0x52,0x52,0x52,0x52,0xFA,0x02,0x02,0x00,/*"道",4*/ 0x48,0x26,0x00,0x10,0x10,0x1F,0x10,0x10,0x00,0x3F,0x68,0xA4,0x21,0x3F,0x00,0x00, 0x20,0x7E,0x80,0x08,0x0C,0xF8,0x10,0x10,0x00,0xC8,0x48,0x48,0x4A,0x41,0x7E,0x00,/*"鸿",5*/ 0x00,0x00,0x7F,0x40,0x41,0x47,0x58,0x41,0x47,0x5C,0x44,0x57,0x4C,0x44,0x44,0x00, 0x01,0x06,0xF8,0x80,0x00,0xFF,0x80,0x00,0xFF,0x92,0x92,0xFE,0x92,0x92,0x92,0x00,/*"雁",6*/ 0x00,0x20,0xFF,0x24,0x24,0x24,0xFF,0x20,0x00,0x7F,0x44,0x44,0x44,0x7F,0x00,0x00, 0x11,0x12,0xF4,0x90,0x90,0x98,0xF5,0x12,0x0C,0xF0,0x40,0x42,0x41,0xFE,0x00,0x00,/*"期",7*/ 0x00,0x08,0x11,0x23,0xCC,0x02,0x12,0x12,0x12,0xFE,0x12,0x13,0x12,0x12,0x02,0x00, 0x40,0x80,0x00,0xFF,0x00,0x40,0x50,0x4C,0x40,0x42,0x41,0xFE,0x40,0x40,0x40,0x00,/*"待",8*/ 0x00,0x00,0x00,0x00,0x01,0x07,0x1F,0x7F,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00, 0x00,0x04,0x1C,0x7C,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0x7C,0x1C,0x04,0x00,0x00,/*"▲",9*/ 0x00,0x03,0x0C,0x10,0x10,0x20,0x21,0x21,0x20,0x10,0x10,0x0C,0x03,0x00,0x00,0x00, 0x00,0xC0,0x30,0x08,0x08,0x04,0x84,0x84,0x04,0x08,0x08,0x30,0xC0,0x00,0x00,0x00,/*"⊙",10*/ 0x00,0x03,0x0C,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x0C,0x03,0x00,0x00,0x00, 0x00,0xC0,0x30,0x08,0x08,0x04,0x04,0x04,0x04,0x08,0x08,0x30,0xC0,0x00,0x00,0x00/*"○",11*/ }; 其显示的显示效果如图1所示,其中的符号"⊙"和"○"就可帮助我们来实现单选处理。 而,则可用于当前选项的指示,这便将它们纳入字库的原因。 当然,若以绘制填充三角形的方式来取代"▲"符号,其指向意义会更明显。 图1 字模显示效果 1)单选 有了单选符号的帮助,在按键的辅助下能轻松地实现单选处理。 实现图2所示效果的程序如下: ShowCHinese(80,100,10,TFT_YELLOW); ShowCHinese(100,100,0,TFT_YELLOW); ShowCHinese(120,100,1,TFT_YELLOW); ShowCHinese(140,100,2,TFT_YELLOW); ShowCHinese(80,120,11,TFT_YELLOW); ShowCHinese(100,120,3,TFT_YELLOW); ShowCHinese(120,120,4,TFT_YELLOW); ShowCHinese(80,140,11,TFT_YELLOW); ShowCHinese(100,140,5,TFT_YELLOW); ShowCHinese(120,140,6,TFT_YELLOW); ShowCHinese(80,160,11,TFT_YELLOW); ShowCHinese(100,160,7,TFT_YELLOW); ShowCHinese(120,160,8,TFT_YELLOW); 图2 单选控件效果 按键选择的程序为: void setup() { tft.begin(); tft.setRotation(3); tft.fillScreen(TFT_RED); ShowCHinese(80,100,10,TFT_YELLOW); ShowCHinese(100,100,0,TFT_YELLOW); ShowCHinese(120,100,1,TFT_YELLOW); ShowCHinese(140,100,2,TFT_YELLOW); ShowCHinese(80,120,11,TFT_YELLOW); ShowCHinese(100,120,3,TFT_YELLOW); ShowCHinese(120,120,4,TFT_YELLOW); ShowCHinese(80,140,11,TFT_YELLOW); ShowCHinese(100,140,5,TFT_YELLOW); ShowCHinese(120,140,6,TFT_YELLOW); ShowCHinese(80,160,11,TFT_YELLOW); ShowCHinese(100,160,7,TFT_YELLOW); ShowCHinese(120,160,8,TFT_YELLOW); pinMode(WIO_KEY_A, INPUT_PULLUP); pinMode(WIO_KEY_B, INPUT_PULLUP); pinMode(WIO_KEY_C, INPUT_PULLUP); } void loop() { int m; if (digitalRead(WIO_KEY_A) == LOW) { m=100+n*20; tft.fillRect(80, m, 20, 20,TFT_RED); ShowCHinese(80,m,11,TFT_YELLOW); n=(n+1)%4; m=100+n*20; ShowCHinese(80,m,10,TFT_YELLOW); } if (digitalRead(WIO_KEY_B) ==LOW) { m=100+n*20; tft.fillRect(80, m, 20, 20,TFT_RED); ShowCHinese(80,m,11,TFT_YELLOW); if(n>0) n=(n-1)%4; m=100+n*20; ShowCHinese(80,m,10,TFT_YELLOW); } if (digitalRead(WIO_KEY_C) ==LOW) { tft.setTextColor(TFT_YELLOW,TFT_RED); tft.setTextSize(3); tft.drawString("N=", 80, 200); tft.drawNumber(n+1, 120, 200,1); } delay(200); } 图3 选控效果 2)多选 多选标识有2种,即☒和☑。若使用录入字符的方式来提取字模是无效的,此时必须借助图形模式来解决。 以图形模式提取字模的步骤为: (1)在Word中插入特殊符号☑或☒; (2)抓取该特殊符号的图像并粘贴到图形软件中,其画布大小为16*16像素点,然后将其保存到位图文件,见图4所示; 图4 生成位图文件 (3)将字模提取软件PCtoLCD2002切换到图形模式; (4)打开位图文件并点击“生成字模”,见图5所示。 图5 提取字模 获取的3个特殊符号字模为: 0x00,0x00,0x3F,0x28,0x28,0x24,0x22,0x21,0x21,0x22,0x24,0x28,0x28,0x3F,0x00,0x00, 0x00,0x00,0xFC,0x0C,0x14,0x24,0x44,0x84,0x84,0x44,0x24,0x14,0x0C,0xFC,0x00,0x00,//☒ 12 0x00,0x00,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x00,0x00, 0x00,0x00,0xFC,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0xFC,0x00,0x00,//□ 13 0x00,0x00,0x3F,0x20,0x20,0x20,0x20,0x20,0x21,0x23,0x27,0x26,0x2E,0x3F,0x10,0x00, 0x00,0x40,0xFC,0x74,0x3C,0x1C,0x34,0xE4,0xC4,0x84,0x04,0x04,0x04,0xFC,0x00,0x00,// ☑ 14 有了多选符号,要实现图6的显示效果其程序为: ShowCHinese(80,100,14,TFT_YELLOW); ShowCHinese(100,100,0,TFT_YELLOW); ShowCHinese(120,100,1,TFT_YELLOW); ShowCHinese(140,100,2,TFT_YELLOW); ShowCHinese(80,120,13,TFT_YELLOW); ShowCHinese(100,120,3,TFT_YELLOW); ShowCHinese(120,120,4,TFT_YELLOW); ShowCHinese(80,140,14,TFT_YELLOW); ShowCHinese(100,140,5,TFT_YELLOW); ShowCHinese(120,140,6,TFT_YELLOW); ShowCHinese(80,160,14,TFT_YELLOW); ShowCHinese(100,160,7,TFT_YELLOW); ShowCHinese(120,160,8,TFT_YELLOW); 图6 显示效果一 若使用另一种标识符,则可产生图7的显示效果,其程序为: ShowCHinese(80,100,12,TFT_YELLOW); ShowCHinese(100,100,0,TFT_YELLOW); ShowCHinese(120,100,1,TFT_YELLOW); ShowCHinese(140,100,2,TFT_YELLOW); ShowCHinese(80,120,13,TFT_YELLOW); ShowCHinese(100,120,3,TFT_YELLOW); ShowCHinese(120,120,4,TFT_YELLOW); ShowCHinese(80,140,13,TFT_YELLOW); ShowCHinese(100,140,5,TFT_YELLOW); ShowCHinese(120,140,6,TFT_YELLOW); ShowCHinese(80,160,12,TFT_YELLOW); ShowCHinese(100,160,7,TFT_YELLOW); ShowCHinese(120,160,8,TFT_YELLOW); 图7显示效果二 多选处理的设计思路是,当按下K1键时,当前选项被标上复选标识;若按下K2键,则**下该选项被选取,且在再次按下K1键时,其标识符不被清除;否则再次按下K1键时,该识符将被清除。当按下K3键时,则显示出选择的结果以便验证。 为了防止出现状态**的差错,采取了标识状态与**位的映射处理,实现多选处理的流程如图8所示。 图8 功能处理流程图 多选处理程序如下: void menu() { ShowCHinese(80,100,13,TFT_YELLOW); ShowCHinese(100,100,0,TFT_YELLOW); ShowCHinese(120,100,1,TFT_YELLOW); ShowCHinese(140,100,2,TFT_YELLOW); ShowCHinese(80,120,13,TFT_YELLOW); ShowCHinese(100,120,3,TFT_YELLOW); ShowCHinese(120,120,4,TFT_YELLOW); ShowCHinese(80,140,13,TFT_YELLOW); ShowCHinese(100,140,5,TFT_YELLOW); ShowCHinese(120,140,6,TFT_YELLOW); ShowCHinese(80,160,13,TFT_YELLOW); ShowCHinese(100,160,7,TFT_YELLOW); ShowCHinese(120,160,8,TFT_YELLOW); } void setup() { int32_t x,y,w,h; tft.begin(); tft.setRotation(3); tft.fillScreen(TFT_RED); menu(); tft.setTextSize(3); tft.setTextColor(TFT_YELLOW, TFT_RED); pinMode(WIO_KEY_A, INPUT_PULLUP); pinMode(WIO_KEY_B, INPUT_PULLUP); pinMode(WIO_KEY_C, INPUT_PULLUP); } void loop() { int m; if (digitalRead(WIO_KEY_C) == LOW) { if(n%4==0) { f=0; n=0; u=n; tft.drawString("M=", 80, 200); tft.drawNumber(u, 120, 200, 1); tft.fillRect(80, 160, 20, 20, TFT_RED); ShowCHinese(80,100,12,TFT_YELLOW); ShowCHinese(80,120,13,TFT_YELLOW); ShowCHinese(80,140,13,TFT_YELLOW); ShowCHinese(80,160,13,TFT_YELLOW); n=(n+1)%4; } else { n=(n-1)%4; m=100+(n%4)*20; if(f==0) { tft.fillRect(80, m, 20, 20,TFT_RED); ShowCHinese(80,m,13,TFT_YELLOW); } else { f=0; } n=(n+1)%4; u=n; tft.drawNumber(u, 120, 200, 1); m=100+(n%4)*20; ShowCHinese(80,m,12,TFT_YELLOW); n=(n+1)%4; } } if (digitalRead(WIO_KEY_B) == LOW) { f=1; s |= (0x01<<u); } if (digitalRead(WIO_KEY_A) == LOW) { tft.drawString("N=", 180, 200); tft.drawNumber(s, 220, 200, 1); while(digitalRead(WIO_KEY_A) == LOW); s=0; } delay(200); } 在编译与上传后,其运行效果如图9所示。 图9 多选效果 3)文本框与按键 文本框是用于输入信息的控件,按键则是用于执行相应操作的控件,在Wio终端由于缺少键盘和鼠标之类的输入设备,故此类控件所存在的意义在于标识其此类控件的性能和属性。 制作此类控件的效果是由填充的矩形及相应的深浅边框构成的,其显示效果如图10所示。 图10文本框与按键 实现显示效果的程序为: tft.fillScreen(TFT_RED); x=100; y=80; w=100; h=30; tft.fillRect(x, y, w, h,TFT_WHITE); tft.drawFastHLine(x, y,w-1,TFT_BLACK); tft.drawFastHLine(x, y+h-1,w,TFT_LIGHTGREY); tft.drawFastVLine(x, y, h,TFT_BLACK); tft.drawFastVLine(x+w-1, y+1,h-1,TFT_LIGHTGREY); ShowCHinese(x+23,y+6,0,TFT_BLACK); ShowCHinese(x+43,y+6,1,TFT_BLACK); ShowCHinese(x+63,y+6,2,TFT_BLACK); x=100; y=130; tft.fillRect(x, y, w, h,TFT_LIGHTGREY); tft.drawFastHLine(x, y,w-1,TFT_WHITE); tft.drawFastHLine(x, y+h-1,w,TFT_BLACK); tft.drawFastVLine(x, y, h,TFT_WHITE); tft.drawFastVLine(x+w-1, y+1,h-1,TFT_BLACK); ShowCHinese(x+23,y+6,0,TFT_BLACK); ShowCHinese(x+43,y+6,1,TFT_BLACK); ShowCHinese(x+63,y+6,2,TFT_BLACK); 鉴于界面的按键与操控的实际按键存在这一定的对应关系,故其处理程序这里从略。 4)选项处理 对于图11所示的功能性选项处理,需有相应标识符的配合,但字符“▲”却据实际需要有些差距,需进行旋转处理。 图11 选项处理 要使用字模提取软件进行处理,其方法为: (1)在字模提取软件中输入字符“▲”; (2)使用“文字右旋90度”工具图标来旋转字模; (3)点击“生成字模”按钮即可,其结果如图12所示。 图12 旋转字模 所获取的字模为: {0x00,0x00,0x7F,0x3F,0x3F,0x1F,0x1F,0x0F,0x0F,0x07,0x07,0x03,0x03,0x01,0x01,0x00}, {0x00,0x00,0xFC,0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00},/*"▲转置"*/ 功能性按键选择的程序为: void setup() { tft.begin(); tft.setRotation(3); tft.fillScreen(TFT_RED); ShowCHinese(80,100,12,TFT_YELLOW); ShowCHinese(100,100,0,TFT_YELLOW); ShowCHinese(120,100,1,TFT_YELLOW); ShowCHinese(140,100,2,TFT_YELLOW); ShowCHinese(100,120,3,TFT_YELLOW); ShowCHinese(120,120,4,TFT_YELLOW); ShowCHinese(100,140,5,TFT_YELLOW); ShowCHinese(120,140,6,TFT_YELLOW); ShowCHinese(100,160,7,TFT_YELLOW); ShowCHinese(120,160,8,TFT_YELLOW); pinMode(WIO_KEY_A, INPUT_PULLUP); pinMode(WIO_KEY_B, INPUT_PULLUP); pinMode(WIO_KEY_C, INPUT_PULLUP); } void loop() { int m; if (digitalRead(WIO_KEY_A) ==LOW) { m=100+n*20; tft.fillRect(80, m, 20, 20,TFT_RED); n=(n+1)%4; m=100+n*20; ShowCHinese(80,m,12,TFT_YELLOW); } if (digitalRead(WIO_KEY_B) ==LOW) { m=100+n*20; tft.fillRect(80, m, 20, 20,TFT_RED); if(n>0) n=(n-1)%4; m=100+n*20; ShowCHinese(80,m,12,TFT_YELLOW); } if (digitalRead(WIO_KEY_C) ==LOW) { tft.setTextColor(TFT_YELLOW,TFT_RED); tft.setTextSize(3); tft.drawString("N=", 80, 200); tft.drawNumber(n+1, 120, 200,1); } delay(200); } 在编译与上传后,其运行效果如图13所示。 图13选控效果 对于下拉菜单和下拉列表,其选取方式如图14所示。 图14 下拉式选取 色块式标识下拉选择的程序为: void m1() { ShowCHinese(100,100,0,TFT_BLACK); ShowCHinese(120,100,1,TFT_BLACK); ShowCHinese(140,100,2,TFT_BLACK); } void m2() { ShowCHinese(100,120,3,TFT_BLACK); ShowCHinese(120,120,4,TFT_BLACK); } void m3() { ShowCHinese(100,140,5,TFT_BLACK); ShowCHinese(120,140,6,TFT_BLACK); } void m4() { ShowCHinese(100,160,7,TFT_BLACK); ShowCHinese(120,160,8,TFT_BLACK); } void setup() { int32_t x,y,w,h; tft.begin(); tft.setRotation(3); tft.fillScreen(TFT_LIGHTGREY); tft.fillRect(90, 98, 80, 81,TFT_WHITE); tft.fillRect(91, 99, 79, 20,TFT_LIGHTGREY); tft.drawRect(90, 98, 80, 82,TFT_BLACK); m1(); m2(); m3(); m4(); pinMode(WIO_KEY_A, INPUT_PULLUP); pinMode(WIO_KEY_B, INPUT_PULLUP); pinMode(WIO_KEY_C, INPUT_PULLUP); } void loop() { int m; if (digitalRead(WIO_KEY_A) ==LOW) { m=99+n*20; tft.fillRect(91, m, 78, 20,TFT_WHITE); if(n==0) m1(); if(n==1) m2(); if(n==2) m3(); if(n==3) m4(); n=(n+1)%4; m=99+n*20; tft.fillRect(91, m, 78, 20,TFT_LIGHTGREY); if(n==0) m1(); if(n==1) m2(); if(n==2) m3(); if(n==3) m4(); } if (digitalRead(WIO_KEY_B) ==LOW) { m=99+n*20; tft.fillRect(91, m, 78, 20,TFT_WHITE); if(n==0) m1(); if(n==1) m2(); if(n==2) m3(); if(n==3) m4(); if(n>0) n=(n-1)%4; m=99+n*20; tft.fillRect(91, m, 78, 20,TFT_LIGHTGREY); if(n==0) m1(); if(n==1) m2(); if(n==2) m3(); if(n==3) m4(); } if (digitalRead(WIO_KEY_C) ==LOW) { tft.setTextColor(TFT_YELLOW,TFT_LIGHTGREY); tft.setTextSize(3); tft.drawString("N=", 80, 200); tft.drawNumber(n+1, 120, 200,1); } delay(200); } 在编译与上传后,其运行效果如图15所示。 图15 下拉式选取 5)选项卡 选项卡是一种分类显示信息的结构形式,其作用类似于多窗口间的切换,其显示效果如图16所示。 图16选项卡效果 选项卡控制的程序为: void setup() { int32_t x,y,w,h; tft.begin(); tft.setRotation(3); tft.fillScreen(TFT_LIGHTGREY); tft.fillRect(20, 18, 280, 200,TFT_WHITE); tft.drawFastHLine(20, 42,280,TFT_BLACK); tft.drawFastVLine(120, 18, 24,TFT_BLACK); tft.drawFastVLine(200, 18, 24,TFT_BLACK); tft.drawFastHLine(20, 42,100,TFT_WHITE); ShowCHinese(60,22,3,TFT_BLACK); ShowCHinese(80,22,4,TFT_BLACK); ShowCHinese(140,22,5,TFT_BLACK); ShowCHinese(160,22,6,TFT_BLACK); ShowCHinese(220,22,7,TFT_BLACK); ShowCHinese(240,22,8,TFT_BLACK); pinMode(WIO_KEY_A, INPUT_PULLUP); pinMode(WIO_KEY_B, INPUT_PULLUP); pinMode(WIO_KEY_C, INPUT_PULLUP); tft.setTextSize(4); } void loop() { if (digitalRead(WIO_KEY_C) == LOW){ tft.setTextColor(TFT_LIGHTGREY,TFT_WHITE); if(n==0) { tft.drawFastHLine(200, 42,100,TFT_BLACK); tft.drawFastHLine(20, 42,100,TFT_WHITE); } if(n==1) { tft.drawFastHLine(20, 42,100,TFT_BLACK); tft.drawFastHLine(120, 42,80,TFT_WHITE); } if(n==2) { tft.drawFastHLine(120, 42,80,TFT_BLACK); tft.drawFastHLine(200, 42,100,TFT_WHITE); } tft.drawString("N=",80, 120); tft.drawNumber(n+1, 120, 120,1); n=(n+1)%3; } if (digitalRead(WIO_KEY_B) == LOW){ } if (digitalRead(WIO_KEY_A) == LOW){ tft.fillScreen(TFT_LIGHTGREY); tft.setTextColor(TFT_WHITE,TFT_LIGHTGREY); tft.drawString(" END", 80, 120); while(1); } delay(200); } 经编译和上传,其运行效果如图17所示。 图17选项卡控制
动画效果: 至此,我们已完成了在显示屏使用方面的介绍,其间所介绍的汉字显示及控件处理方面的内容是对原显示功能的有效补充和扩展,希望能对大家的应用带来益处和启发。其实显示方面的应用还有许多,由于它与硬件的结合比较紧密,故后面会暂时结束在显示方面的盘桓,将介绍的内容转向硬件的性能及其使用方法,若感兴趣不妨持续关注。
|