首页 > 编程语言 >在Lazarus下的Free Pascal编程教程——在Lazarus中使用计时器组件TTimer

在Lazarus下的Free Pascal编程教程——在Lazarus中使用计时器组件TTimer

时间:2024-12-26 15:30:04浏览次数:6  
标签:TTimer Free 添加 计时器 Panel1 组件 Lazarus 方块

0.前言

我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。

了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”和“2.已经编写完成的文章(目录)”:

学习编程从游戏开始——编程计划(目录) - lexyao - 博客园

我已经在下面这篇文章中介绍了使用LCL和FCL组件构建一个项目(pTetris)的过程,后续的使用Lazarus的文章中使用的例子都是以向这个项目添加新功能的方式表述的:

在Lazarus下的Free Pascal编程教程——用向导创建一个使用使用LCL和FCL组件的项目(pTetris) - lexyao - 博客园

在上一篇文章中我们介绍了使用布局组件构建应用程序界面。在界面中用到的组件都是可以看得见的,所以叫做可是组件。在这一篇文章中,我们将会用到另一类组件,一种看不到却在背后默默工作的组件,也叫做非可视组件。

俄罗斯方块游戏中的方块除了游戏玩家有鼠标或者键盘操作的移动、旋转之外,还有有一个不断下落的动作。这个下落的动作是用计时器操作的。在pTetris项目中,有一个叫做TTimer的非可视组件,这就是计时器组件。

在这篇文章里,我主要讲述以下几个方面的内容:

  1. 计时器组件TTimer简介
  2. 向pTetris项目添加一个计时器组件
  3. 计时器组件使用示例
  4. 结束语

了解不同方式实现同样效果的差异,请阅读以下文章:

 

1.计时器组件TTimer简介

每个操作系统都有计时器组件。在Lazarus中计时器组件是TTimer。
TTimer ttimer.png 是 Component Palette 的 System 选项卡上的组件,它提供通常具有毫秒分辨率的计时器。它从 TCustomTimer 继承其大部分属性。它在 ExtCtrls 单元中定义。
以下是Lazarus Wiki和帮助文件中介绍TTimer的网址链接。在看本文下面的内容之前,希望能先看一看Lazarus的介绍。

从TTimer的帮助文件中,我们看到它定义了以下成员:

属性 Enabled: Boolean; 指示计时器是否已准备好启动。
属性 Interval: Cardinal; 计时器通知的时间间隔 (以毫秒为单位)。
事件 OnTimer: TNotifyEvent;

事件处理程序在计时器的 Interval 已过时发出信号。

事件 OnStartTimer: TNotifyEvent; 事件处理程序在计时器启动时发出信号。
事件 OnStopTimer: TNotifyEvent; 用于停止计时器的事件处理程序。

 

2.向pTetris项目添加一个计时器组件

在Lazaus中向应用程序添加计时器,跟添加其他的可视组件一样,只要在组件面板中双击TTimer图标,一个计时器组件就添加添加到窗体设计器的应用程序的界面中了。
TTimer虽然在运行时看不到,但设计时在窗体设计器中还是能看到它的图标的。这个图标只是表示计时器的存在,它的位置不影响它的使用。通常我们只是为了使用方便把它放到一个自己认为合适的地方。比如:在pTetris项目中我们是用它来控制pnBox中移动的方块的,我们就把它拖放到pnBox上。
在pTetris项目中,我们添加一个TTimer组件,Name属性自动命名为Timer1。记住这个名字,在以后的文章中还会用到。

3.计时器组件使用示例

为了演示计时器的使用,我们添加一个使用计时器事件移动方块的代码。
首先,打开pTetris项目,向主窗口的pnBox中添加一个TPanel组件,Name属性自动设置为Panel1。在属性列表中设置Panel1的属性:

  • 设置Color为clRed,面板表面变为红色
  • 设置Height、Width为17,变成一个17x17的小方块

然后,为计时器组件Timer1添加事件处理代码。在组件列表或窗体设计器中双击Timer1,会看到代码编辑器中添加给TfrmMain添加了一个成员函数。在定义中添加了以下代码:

procedure Timer1Timer(Sender: TObject); 

在实现区域添加了以下代码:

procedure TfrmMain.Timer1Timer(Sender: TObject);
begin

end;   

我只需要在实现区域添加定时器动作需要的代码就行了。作为一个演示,在这里我们添加的代码是让小方块Panel1在pnBox中移动,与宝玉道边框后反弹。代码如下:

procedure TfrmMain.Timer1Timer(Sender: TObject);
var
   xx,yy:integer;
begin
  if dx=0 then dx:=1;
  if dy=0 then dy:=1;
  xx:=Panel1.Left+Panel1.Width*dx;
  yy:=Panel1.Top+Panel1.Height*dy;
  if xx<0 then
  begin
    dx:=-dx;
    xx:=0;
  end
  else if xx>=pnBox.Width-Panel1.Width then
  begin
    dx:=-dx;
    xx:=pnBox.Width-Panel1.Width;
  end;

  if yy<0 then
  begin
    dy:=-dy;
    yy:=0;
  end
  else if yy>=pnBox.Height-Panel1.Height then
  begin
    dy:=-dy;
    yy:=pnBox.Height-Panel1.Height;
  end;
   Panel1.Left:=xx;
   Panel1.Top:=yy;
end; 

编译运行pTetris项目,查看运行的效果。这时我们看到pnBox中有一个红色的小方块一直不停地跳动,每隔1秒跳动一次,沿着斜线前进,遇到边框就按45°夹角反弹后继续移动。只要程序不关闭窗口,它会一直跳动。

关闭pTetris项目的运行窗口,在设计器中选中Timer1,在属性列表中修改属性Interval的值,然后重新编译运行,查看有什么变化。
Interval是计时器通知的时间间隔,也就是方块跳动的时间间隔。它是以毫秒计算的。把这个值设置的越小,方块跳动得就越快。

现在看到了方块跳动,也有了改变方块跳动速度的方法,美中不足的是方块一直跳动,就是不停下来。
下面我添加一个新的功能:通过点击pnBox下面的“暂停”按钮,让方块按着我们的意愿停止跳动或者继续跳动。为此,我需要添加一个事件处理程序。
在窗体设计器中双击“暂停”按钮,代码窗口中添加了点击在暂停按钮的事件处理程序,我们添加如下代码:

procedure TfrmMain.btnPauseClick(Sender: TObject);
begin
  Timer1.Enabled:=not Timer1.Enabled;
end;  

在代码中我们设置Timer1的Enabled属性,让程序运行时,如果方块移动时点击暂停按钮,方块就停止跳动,方块静止时点击暂停按钮,方块又开始跳动。
虽然编译运行后看到了预期的效果,但总是感觉有些别扭:点击“暂停”让方块动起来。如果在方块静止的时候暂停按钮的文字变成“恢复”,我们点击“恢复”让方块恢复跳动,这样是不是更好呢?
为了达到这样的效果,我们再给Timer1添加两个事件处理程序。
在组件列表或窗体设计器中选中Timer1,再点击属性列表中的“事件”,显示出Timer1可用的事件列表。双击前两个事件,在代码中添加两个事件处理函数,然后再添加如下代码:

procedure TfrmMain.Timer1StartTimer(Sender: TObject);
begin
  btnPause.Caption:='暂停' ;
end;

procedure TfrmMain.Timer1StopTimer(Sender: TObject);
begin
  btnPause.Caption:='恢复';
end; 

编译运行,这时我们看到:方块开始跳动时btnPause按钮的标题是“暂停”,方块静止时btnPause按钮的标题是“恢复”。这样用起来就没有困惑了。

在这里也看到了添加事件处理程序的操作方法的不同:
添加Timer1Timer、btnPauseClick时我们时通过双击组件添加的,这是因为他们是组件的默认事件。
添加Timer1StartTimer、Timer1StopTimer是我们是在事件列表中添加的,添加非默认事件都是要这样操作。


4.结束语

在这一篇文章里,我们了解了在Lazarus中使用计时器组件的方法,也了解了添加默认事件和非默认事件处理程序的差别。
编写事件处理程序是图形界面操作系统编程的一个重要的内容。在编写事件处理程序的时候要记住一点:需要长时间操作的事件处理会导致程序停止动作,等待事件处理程序执行完成。在此期间程序就像卡死了一样。为了避免这种假死现象,让操作着感到困惑,通常有两种方案:

  • 显示一个能显示动作进度的界面提示,让操作者指导事情还没有做完,请耐心等待
  • 把耗时很长的操作放入另一个线程中去完成,这样界面就不会卡死了

 

标签:TTimer,Free,添加,计时器,Panel1,组件,Lazarus,方块
From: https://www.cnblogs.com/lexyao/p/18632986

相关文章

  • 在Lazarus下的Free Pascal编程教程——使用LCL布局组件构建应用程序主窗口布局
    0.前言我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”和“2.已......
  • 在Lazarus下的Free Pascal编程教程——Lazarus的LCL布局组件简介
    0.前言我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”和“2.已......
  • Economic-Statistics-Experiment-Design&Analysis-: 统计: 试验设计与分析: 5 Free Re
    Economic-Statistics-Experiment-Design&Analysis-:5FreeResourcesforLearningExperimentalDesigninStatisticsbyVinodChuganiPostedonAugust26,2024Experimentaldesignisafundamentalcomponentofstatisticalanalysis,enablingresearchersto......
  • 与程序设计有关的网址收藏C/C++(CodeBlocks/wxWidgets)、Pascal(Lazarus/Delphi/LCL/FCL)
    0.前言在网上查看资料的时候,经常会看到一些好的文章,这些文章介绍的知识点可能是当时使用的,也可能是以后能用得着的。对于那些以后能用得着的知识点,有时在用到的时候在想找却忘记了是在哪一篇文章里了,或者再搜索却搜索不到了。通常遇到以后可能需要的文章,最好的办法是收藏。可是......
  • freeswitch(多方同振、多方顺振)
    亲测版本centos7.9系统–》freeswitch1.10.9本人freeswitch安装路径(根据自己的路径进入)/usr/local/freeswitch/etc/freeswitch使用场景:同振:比如B绑定C、D、F三个设备,A呼叫B时候,C、D、F同时响铃,只要B、C、D、F任意一台设备接听,其他设备将会停止不响。顺振:比如B......
  • 【学习】lazarus的Laz2_XMLCfg用法
    lazarus的lpi等文件都是使用XML格式,使用Laz2_XMLCfg可以方便读写这类XML配置文件。0、在uses添加Laz2_XMLCfg单元。1、下面的例子是读取ProjectOptions/Units所有unit中FileName<?xmlversion="1.0"encoding="UTF-8"?><CONFIG><ProjectOptions><Units><......
  • 推荐一个开源大模型呼叫中心系统FreeAICC
    推荐一个开源大模型呼叫中心系统FreeAICC在当今这个快节奏、高效率的商业环境中,企业与客户之间的有效沟通成为了决定业务成败的关键因素之一。为了帮助企业精准触达目标客户,提升服务效率与质量,我们找到了这个开源大模型呼叫中心系统——一款集智能外呼、呼入机器人、人工坐席......
  • 在Lazarus下的Free Pascal编程教程——用向导创建一个使用使用LCL和FCL组件的项目(pTet
    0.前言我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”:学习编程......
  • freertos入门---堆的概念
    freertos入门—堆的概念  堆就是一块空闲的内存。下面举个例子更好的理解堆的概念:  堆是一块空闲的内存,我们可以定义一个数组charheap_buf[1024],可以看到该数组就是一个空闲的内存,我们只需要在它上面实现内存的分配和释放那么它就一个堆。charheap_buf[1024]; ......
  • 论文速读,YOLOX:anchor free的单阶段目标检测模型
    原文标题:YOLOX:ExceedingYOLOSeriesin2021中文标题:YOLOX:2021年超越YOLO系列代码地址:https://github.com/Megvii-BaseDetection/YOLOXAbstract在本报告中,旷视团队介绍了对YOLO系列的一些经验丰富的改进,形成了一种新的高性能检测器——YOLOX。我们将YOLO检测器切......