2015-09-05 69 views
1

即时试图使一个按钮从(0.0)移动到(500.500),选择那些我用一个循环,并如上面的代码中的线程休眠过程:的Delphi按钮消失

 unit Unit1; 

     interface 

     uses 
     Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
     Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

     type 
     TForm1 = class(TForm) 
      TbuttonAction: TButton; 
      procedure show(Sender: TObject); 
     private 
     { Déclarations privées } 
     public 
     { Déclarations publiques } 
     end; 

     var 
     Form1: TForm1; 

     implementation 

     {$R *.dfm} 

     procedure TForm1.show(Sender: TObject); 
     var 
      i: Integer; 
     begin 
      TbuttonAction.Caption:='my first action'; 

      for i := 0 to 500 do 
      begin 

       TThread.Sleep(10); 
       TbuttonAction.Top:=i; 
       TbuttonAction.Left:=i; 

       end; 
       end; 
      end. 

第一次单击按钮从0.0移动到500.500,但如果我点击另一次(第二次或第三次当按钮在500.500上),按钮消失,然后出现一段时间后。请问如何解决这个问题?我今天开始delphi,但我很好用java(3年)。

+0

我使用embarcadero Xe 8 –

+0

@JerryDodge我试过了但仍然消失,循环从0.0开始 –

+1

我认为使用线程sleep会终止元素的绘制。有没有一种启动线程的方法(使用运行方法创建新的线程来控制移动动作?) –

回答

2

发生这种情况的原因大概是因为您没有抽取消息队列。 Windows应用程序需要主UI线程及时地处理其消息队列,以便处理绘画和输入等内容。你用繁忙的循环阻塞主线程。

删除循环,而是添加一个计时器。定时器通过消息循环生成的消息进行操作,因此不会阻塞主UI线程。

给定时器一个适当的间隔,比如100ms。当你想开始动画时,将定时器的Enabled属性设置为True

procedure TForm1.Show(Sender: TObject); 
begin 
    Button1.Left := 0; 
    Button1.Top := 0; 
    Timer1.Interval := 100; 
    Timer1.Enabled := True; 
end; 

这样实现定时器的OnTimer事件:

procedure TForm1.Timer1Timer(Sender: TObject); 
var 
    Pos: Integer; 
begin 
    Pos := Button1.Left + 10; 
    Button1.Left := Pos; 
    Button1.Top := Pos; 
    if Pos >= 500 then 
    Timer1.Enabled := False; 
end; 

我改名为您的按钮。前缀T用于类型,不用于实例。

作为一个宽泛的指南,Sleep永远不应该在UI程序的主线程中调用。我不认为有很多,如果的确有任何例外。睡觉停止UI线程服务其消息队列。