2015-09-05 105 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線程服務其消息隊列。