问题
之前的文章中描述的滚动文本更新文本的方式有缺点。
缺点一:滚动文本的属性dir由1或0改回2或3,再改回1或0,。这个过程滚动文本控件中的文字会出现短暂的闪烁
缺点二:如果不更改滚动文本控件的属性dir,那么随着程序运行时间的增长,会发现滚动文本控件中的文字更新的地方,不再是开始的位置,而是在移动。
下面说一下针对上述的问题的解决办法
前言:假设查询异常信息的指令是“Third\r”,无异常返回的数据是"0000000";有异常对应位置的数据为1.(这里的0或1是十六进制的0或1)
这里先规定对应位置的数据为1是代表的是什么异常信息:
- 第0个位置为1:Alarm_1
- 第1个位置为1:Alarm_2
- 第2个位置为1:Alarm_3
- 第3个位置为1:Alarm_4
- 第4个位置为1:Alarm_5
- 第5个位置为1:Alarm_6
- 第6个位置为1:Alarm_7
下面开始
1、创建全局的字符串变量
为什么是全局?
怎么说呢。如果你的异常信息只会在某个页面出现,别的地方不会用到,那就局部变量就行。
2、创建所需要的控件和函数
前初始化事件
界面中显示的控件
发送指令函数
//*******************************************************************************
// 发送指令
//******************************************************************************/
va1.val=cmd.val%2
if(va1.val==0)
{
temp_sts.txt="First"
tm0.tim=400 // 每个指令的有不同的等待数据返回时间
}else
{
if(cmd.val==1)
{
temp_sts.txt="Null"
tm0.tim=300 // 每个指令的有不同的等待数据返回时间
}else if(cmd.val==3)
{
temp_sts.txt="Second"
tm0.tim=300 // 每个指令的有不同的等待数据返回时间
}else if(cmd.val==5)
{
temp_sts.txt="Third"
tm0.tim=400 // 每个指令的有不同的等待数据返回时间
}else
{
tm0.tim=50
}
}
//
if(temp_sts.txt!="Null") // 通过串口发送指令
{
prints temp_sts.txt,0
}else
{
printh EE
printh FF
}
printh 0D // 帧尾 是十六进制发送
//
// 开启调用对应处理返回数据函数的定时器
tm0.en=1
处理Third\r指令的函数
//*******************************************************************************
// 函数
//******************************************************************************/
if(usize>=6) // 如果串口缓冲区的数据字节长度>=6
{
t1.txt="start"
// &Ascii码的十六进制0x26
// 如果当前串口缓冲区的第一个字节数据是 0x26 ,如果数据尾有校验(比如数据尾的最后一个字节数据为0x0D)
if(u[0]==0x26&&u[8]==0x0D) // 这里假设返回的正确长度为9个字节
{
t1.txt+="success"
// 接收成功
cmd.val++
//
//
temp_1.val=1 // 去掉数据头
Usizes.val=usize-1 // 去掉数据尾
New_info.txt="" // 清空
while(temp_1.val<Usizes.val)
{
if(u[temp_1.val]==0x31) // 1的Ascii码为49,十六进制就是31 0的Ascii码为48,十六进制就是30
{
New_info.txt+="1" // 有异常
}else
{
New_info.txt+="0" // 无异常
}
temp_1.val++
}
//
// 处理异常
click handle_excep,1
}
}
t0.txt="Detecting abnormal information"
handle_excep的按下事件和弹起事件中的函数
按下事件
//*******************************************************************************
// 函数
//******************************************************************************/
//
// 判断是否有异常或是否有异常更新
if(New_info.txt==No_exception.txt) // 无异常
{
Old_info.txt=New_info.txt // 消除当前正在显示ID异常信息
vis g0,0 // 隐藏滚动文本
g0.en=0 // 关闭滚动文本
va0.val=0 // 清零滚动时长计数
RefshFlag.val=0 // 清零
tm1.en=0 // 关闭调用更新滚动文本函数的定时器
//
}else // 有异常
{
if(Old_info.txt!=New_info.txt) // 新旧信息不一致,表示有新的异常信息
{
if(va0.val==0) // 如果有异常信息正在滚动,等待其滚动完成
{
Old_info.txt=New_info.txt // 更新异常信息
g0.txt="" // 清空滚动文本
if(g0.en!=1)
{
g0.en=1 // 启动滚动文本
}
tm1.en=1 // 启动调用更新滚动文本函数的定时器
RefshFlag.val=1 // 更新完成标志
doevents
}
}else
{
if(tm1.en!=1)
{
tm1.en=1 // 防止调用更新滚动文本函数的定时器没有启动
}
}
vis g0,1 // 显示滚动文本
}
弹起事件中的函数
while(DisplayFlag.val==0&&FalsePosion.val<7)
{
substr Old_info.txt,temp_sts.txt,FalsePosion.val,1 // 截取一个字符
FalsePosion.val++ // 截取位置+1
if(temp_sts.txt=="1") // 判断该字符是不是1,及是不是异常
{
DisplayFlag.val=1
}
}
//
//
TruePosion.val=FalsePosion.val-1 // 必须要减去1,因为字符串中的位置从0开始
if(TruePosion.val==0&&DisplayFlag.val==1)
{
g0.txt="Alarm_1"
va0.val=68 // 滚动时长
}else if(TruePosion.val==1&&DisplayFlag.val==1)
{
g0.txt="Alarm_2"
va0.val=68 // 滚动时长
}else if(TruePosion.val==2&&DisplayFlag.val==1)
{
g0.txt="Alarm_3"
va0.val=68 // 滚动时长
}else if(TruePosion.val==3&&DisplayFlag.val==1)
{
g0.txt="Alarm_4"
va0.val=64 // 滚动时长
}else if(TruePosion.val==4&&DisplayFlag.val==1)
{
g0.txt="Alarm_5"
va0.val=68 // 滚动时长
}else if(TruePosion.val==5&&DisplayFlag.val==1)
{
g0.txt="Alarm_6"
va0.val=68 // 滚动时长
}else if(TruePosion.val==6&&DisplayFlag.val==1)
{
g0.txt="Alarm_7"
va0.val=68 // 滚动时长
}else
{
FalsePosion.val=0 // 重新开始显示信息
}
//
// 这里是必要的为了解决文章中说的问题
ScrollTempS.txt=g0.txt // 临时保存异常信息
g0.txt="" // 清空滚动文本
调用函数的定时器
代码如下:
//*******************************************************************************
// 执行对应的函数,获取数据
//******************************************************************************/
FailCnt.val=cmd.val // 如果执行完下面的函数 ,FailCnt.val==cmd.val,,那么判断接收失败
if(va1.val==0)
{
click First,1
}else
{
if(cmd.val==1)
{
click Null,1
}else if(cmd.val==3)
{
click Second,1
}else if(cmd.val==5)
{
click scroll_func,1 // 检测是否有异常信息更新
}else
{
cmd.val=0 // 指令计数归零,重新开始
}
}
//
code_c
//
// 当从串口换从取读取没有读取到符合要求的数据3次,那么就执行下一条指令
if(FailCnt.val==cmd.val)
{
NextCmd.val++
if(NextCmd.val>=3)
{
NextCmd.val=0
cmd.val++
}
}else
{
NextCmd.val=0
}
//
// 关闭定时器,因为定时器会每隔设定的时间就执行一次
tm0.en=0
// 执行发送指令任务
click func,1
定时器tm1:记录当前滚动文本的滚动时间和调用更新当前显示的函数
代码如下:
//*******************************************************************************
// 同步记录每条信息滚动时间,达到每条信息滚动的时间之后,切换信息
//******************************************************************************/
if(va0.val==0)
{
if(Old_info.txt!=New_info.txt) // 异常有更新
{
if(RefshFlag.val==1) // 更新完毕
{
RefshFlag.val=0 // 清零更新完成标志
g0.dir=2 // 更改滚动文本滚动方向
click handle_excep,0
}else // 没有更新完成,继续等待更新完成
{
g0.txt="" // 清空滚动文本中显示的内容
tm1.en=0
click handle_excep,1
}
}else // 无异常更新,在已有的异常信息中切换下一个异常信息显示
{
DisplayFlag.val=0 // 清零标志,准备切换下一条信息
g0.dir=2
click handle_excep,0
}
DisplayCnt.val=0 // 清理计数变量
}else
{
va0.val--
DisplayCnt.val++
if(DisplayCnt.val!=4) // Loop
{
if(DisplayCnt.val>=2) //
{
if(g0.dir!=1) // 将滚动文本的滚动方向,变回原来的滚动方向
{
g0.dir=1
g0.txt="" // 避免出现更新滚动文本时出现,文本闪烁的情况
}
if(DisplayCnt.val>=3&&g0.dir==1)
{
g0.txt=ScrollTempS.txt // 获取当前要滚动的文本
DisplayCnt.val=4 // 执行到这里,那么下一次就不需要执行Loop里面的语句
}
}
}
}
3、实现的效果
4、针对代码中使用得到的变量说明
以上就是我针对,这个滚动文本遇见的问题和解决办法。我感觉这个滚动文本最难的应该就是这里了。
希望对有需要的人有帮助。