Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2015-11

Event created by program logic rather than user action

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Dr Engelbert Buxbaum

Hi,

I am writing a cellular automaton, that calculates a n by n array with integer values, which represent colour values. The array is updated in an infinite loop, that I want to also call the FormPaint method to create a graphical representation of the automaton. Who is the sender in this case? Or is there a better way to do this?

Thanks for any help

Engelbert

unit CellularAutomaton;
{$mode objfpc}{$H+}
interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,

  crt, LResources, BGRABitmap, BGRABitmapTypes;
type
  { TForm1 }
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.lfm}
var Image : TBGRABitmap;
// code of no relevance to the question goes here

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image := TBGRABitmap.Create(ScreenSize,ScreenSize,BGRABlack);
end;
procedure TForm1.FormPaint(Sender: TObject);
var p: PBGRAPixel;
    x,y: integer;
begin
  for y := 0 to Image.Height-1 do
    begin
      p := Image.Scanline[y];
      for x := 0 to Image.Width-1 do
        begin
          IntToRGB(NewScreen[succ(y),succ(x)],p^.red, p^.green, p^.blue);
          inc(p);
        end;
    end;
  Image.InvalidateBitmap;  //  direkt Pixels access
  Image.Draw(Canvas,0,0,True);
  Image.Free;
end;
begin
  Initialize(OldScreen);
  Initialize(NewScreen);
  repeat
    Calculate(OldScreen, NewScreen);
    CopyScreen(NewScreen, OldScreen);
    TForm1.FormPaint(????????);
  until keypressed;
end.

Reply by email

Anthony Walter
to Anthony Walter

Here's an example which calculates Pi forever in a thread. It's important to note a few things:

1. Periodically check if the thread should stop by checking the Terminated property inside Execute
2. If you want to communicate with the user interface, such as refreshing the screen based on some calculations, use the Synchronize method to do so
3. Do not share data the thread is using in calculations with anything. If you need access to the data in somewhere else, use Synchronize and make a copy there.

unit Main;
{$mode delphi}
interface
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

{ TMainForm }

type
  TMainForm = class(TForm)
    OutputLabel: TLabel;
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    FThread: TThread;
  end;
var
  MainForm: TMainForm;
implementation
{$R *.lfm}

{ TCalculatePiThread }

type
  TCalculatePiThread = class(TThread)
  private
    FPiDigits: string;
  protected
    procedure Update;
    procedure Execute; override;
  end;
procedure TCalculatePiThread.Update;
begin
  MainForm.OutputLabel.Caption := FPiDigits;
end;
procedure TCalculatePiThread.Execute;
var
  Data: array[0..2801] of Integer;
  I, K, B, D, C: Integer;
begin
  FreeOnTerminate := True;
  while not Terminated do
  begin
    C := 0;
    for I := Low(Data) to High(Data) do
      Data[I] := 2800;
    K := 2800;
    while K > 0 do
    begin
      K := K - 14;
      D := 0;
      I := K;
      while not Terminated do
      begin
        D := D  + Data[I] * 10000;
        B := 2 * I - 1;
        Data[I] := D mod B;
        D := D div  B;
        Dec(I);
        if I < 1 then
          Break;
        D := D * I;
      end;
      FPiDigits := Format('%.4d', [C + D div 10000]);
      Synchronize(Update);
      C := D mod 10000;
    end;
  end;
end;

{ TMainForm }

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FThread := TCalculatePiThread.Create(False);
end;
procedure TMainForm.FormClose(Sender: TObject; var CloseAction:
TCloseAction);
begin
  FThread.Terminate;
end;

end.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151108/0e13252c/attachment.html>

Reply by email

Michael Schnell
to Anthony Walter
Anthony Walter wrote
2. If you want to communicate with the user interface, such as refreshing the screen based on some calculations, use the Synchronize method to do so

If you don't want to have the thread wait for the mainthread to execute the event, use TThread.Queue (available only as of fpc 3.x) or Application.QueueAsyncCall

3. Do not share data the thread is using in calculations with anything. If you need access to the data in somewhere else, use Synchronize and make a copy there.

If you want to transfer data from the thread to the main thread and don't use TThread.Synchronize, you can use a TThreadList to create a queue of sent data records, or create an object, use a procedure of same in TThread.Queue or Application.QueueAsyncCall and do "Free;" as the last instruction of that Procedure (making it a "finalizer")

-Michael

Reply by email