Recent

Author Topic: [SOLVED] TPanel slider position  (Read 2166 times)

Pe3s

  • Hero Member
  • *****
  • Posts: 533
[SOLVED] TPanel slider position
« on: November 28, 2023, 11:09:59 am »
Hello forum members, what do I need to correct in the code to make the adjustment range -100 - 0 - 100 work?
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  2. begin
  3.   if not(ssLeft in Shift) then Exit;
  4.   Pos := X + Panel2.Left;
  5.   Max := Panel1.ClientWidth - Panel2.Width;
  6.   if Pos < 0 then Pos := 0;
  7.   if Pos > Max then Pos := Max;
  8.   Panel2.Left := Pos;
  9.  
  10.   BGProgress.Value := Round(100 * Pos / Max);
  11.   Form1.Caption := IntToStr(BGProgress.Value);
  12. end;
  13.  
  14. procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
  15.   Shift: TShiftState; X, Y: Integer);
  16. begin
  17.   if not (ssLeft in Shift) then Exit;
  18.   Pos:= X;
  19.   Max := Panel1.ClientWidth - Panel2.Width;
  20.   if Pos < 0 then Pos := 0;
  21.   if Pos > Max then Pos := Max;
  22.   Panel2.Left:= Pos;
  23.  
  24.   BGProgress.Value := Round(100 * Pos / Max);
  25.   Form1.Caption := IntToStr(BGProgress.Value);
  26. end;
« Last Edit: December 03, 2023, 05:47:08 pm by Pe3s »

Handoko

  • Hero Member
  • *****
  • Posts: 5108
  • My goal: build my own game engine using Lazarus
Re: TPanel slider position
« Reply #1 on: November 28, 2023, 01:59:47 pm »
Done.

This is the correct formula:
BGProgress.Value := Round(200 * Pos / Max) - 100;
« Last Edit: November 28, 2023, 02:07:07 pm by Handoko »

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: TPanel slider position
« Reply #2 on: November 28, 2023, 04:20:03 pm »
@Handoko, Thank you for your help :)

Thaddy

  • Hero Member
  • *****
  • Posts: 14031
  • Probably until I exterminate Putin.
Re: [SOLVED] TPanel slider position
« Reply #3 on: November 29, 2023, 09:21:09 am »
I believe the correct formula to be BGProgress.Value := (200 * Pos  div Max) - 100;, Handoko.
That processes completely in the integer domain.
« Last Edit: November 29, 2023, 09:24:00 am by Thaddy »
Specialize a type, not a var.

Handoko

  • Hero Member
  • *****
  • Posts: 5108
  • My goal: build my own game engine using Lazarus
Re: [SOLVED] TPanel slider position
« Reply #4 on: November 30, 2023, 04:07:12 am »
Yes, you're right.

I forgot that div is more efficient than / for result in integer.

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: [SOLVED] TPanel slider position
« Reply #5 on: December 02, 2023, 07:19:15 pm »
I have one more question why the code works with Panel components but not with Image ?

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Panel2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  2. var
  3.   NewX, Max: Integer;
  4. begin
  5.   if not(ssLeft in Shift) then Exit;
  6.   NewX := X + Panel2.Left -20;
  7.   Max := Panel1.ClientWidth - Panel2.Width;
  8.   if NewX < 0 then NewX := 0;
  9.   if NewX > Max then NewX := Max;
  10.   Panel2.Left := NewX;
  11.  
  12.   Label1.Caption := GetPosition.ToString;
  13. end;

Handoko

  • Hero Member
  • *****
  • Posts: 5108
  • My goal: build my own game engine using Lazarus
Re: TPanel slider position
« Reply #6 on: December 02, 2023, 07:50:21 pm »
I modified your code by renaming Panel2 to Image1, it works.

If you can't make it works, please provide a demo so I can download and inspect the problem.

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: TPanel slider position
« Reply #7 on: December 02, 2023, 09:19:05 pm »
TImage counts Positions differently

Handoko

  • Hero Member
  • *****
  • Posts: 5108
  • My goal: build my own game engine using Lazarus
Re: TPanel slider position
« Reply #8 on: December 03, 2023, 04:08:45 am »
Done!

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Image1: TImage;
  16.     Image2: TImage;
  17.     Label1: TLabel;
  18.     procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
  19.       );
  20.   end;
  21.  
  22. var
  23.   Form1: TForm1;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  32. const
  33.   ResultMin = 0;
  34.   ResultMax = 100;
  35. var
  36.   AllowedMin,
  37.   AllowedMax,
  38.   Result:      Integer;
  39. begin
  40.  
  41.   if not(ssLeft in Shift) then Exit;
  42.  
  43.   AllowedMin := Image1.Left;
  44.   AllowedMax := Image1.Left + Image1.Width - Image2.Width;
  45.  
  46.   Image2.Left := Image2.Left + X - (Image2.Width div 2);
  47.   if Image2.Left < AllowedMin then Image2.Left := AllowedMin;
  48.   if Image2.Left > AllowedMax then Image2.Left := AllowedMax;
  49.  
  50.   Result := ((ResultMax-ResultMin) *
  51.             (Image2.Left-AllowedMin) div
  52.             (AllowedMax-AllowedMin)) + ResultMin;
  53.   Label1.Caption := Result.ToString;
  54.  
  55. end;
  56.  
  57. end.

  • First of all, lets talk about moving the handle. See line #46. That may seem complicated. But actually the basic formula is very simple:
    Image2.Left := Image2.Left + X;
  • Now, see the img2 below. Because the handle has width, to make the the pointer to detect the center of the handle, it needs to do:
    - (Image2.Width div 2)
  • Now back to the formula you already know:
    = Round(100 * Pos / Max)
  • Actually the main formula is something like this:
    = ( the_range * position / maximum_allowed ) + starting_value
  • If you want to have -100.0.100 in the result, change the values in the lines #33..#34, and run the code. Now look at the line #50, you can see why the_range becomes ResultMax-ResultMin. And because you want the -100 as the starting_value, you have to do +ResultMin as you see in the line #52.
  • About the div in the formula. Div runs faster than /. And div always gives integer result, so you don't have to do Round.

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: TPanel slider position
« Reply #9 on: December 03, 2023, 10:03:06 am »
@Handoko, I have one more question regarding the onMouseDown procedure, how can I modify the code to move the dot on mouse click?
Change the code on line 46
Code: Pascal  [Select][+][-]
  1. Image2.Left := X;
does not place the dot in the correct position




Handoko

  • Hero Member
  • *****
  • Posts: 5108
  • My goal: build my own game engine using Lazarus
Re: TPanel slider position
« Reply #10 on: December 03, 2023, 10:19:18 am »
Add this Image1.OnClick event:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Image1Click(Sender: TObject);
  2. var
  3.   NewPos:TPoint;
  4. begin
  5.   NewPos := ScreenToClient(Mouse.CursorPos);
  6.   Image2.Left := NewPos.X - (Image2.Width div 2);
  7. end;

You can get the mouse pointer position by using Mouse.CursorPos. But before you can use that values, you need to convert it by using ScreenToClient function.

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: TPanel slider position
« Reply #11 on: December 03, 2023, 10:30:24 am »
@Handoko, I am grateful for your help. Thank you :)
Greetings with a smile

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: [SOLVED] TPanel slider position
« Reply #12 on: December 03, 2023, 12:47:50 pm »
@Handoko, I would also like to ask about automatic ball movement
Code: Pascal  [Select][+][-]
  1. Image2.Left := image1.Width * POS div ResultMax;

Handoko

  • Hero Member
  • *****
  • Posts: 5108
  • My goal: build my own game engine using Lazarus
Re: TPanel slider position
« Reply #13 on: December 03, 2023, 02:41:25 pm »
Not sure what did you mean. Maybe something like this:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Image1: TImage;
  16.     Image2: TImage;
  17.     Label1: TLabel;
  18.     lbeGoto: TLabeledEdit;
  19.     lbeResultMax: TLabeledEdit;
  20.     lbeResultMin: TLabeledEdit;
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure Image1Click(Sender: TObject);
  23.     procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
  24.       );
  25.     procedure lbeGotoEditingDone(Sender: TObject);
  26.     procedure lbeResultMaxEditingDone(Sender: TObject);
  27.     procedure lbeResultMinEditingDone(Sender: TObject);
  28.   private
  29.     FResultMin: Integer;
  30.     FResultMax: Integer;
  31.     procedure CalculatePosition;
  32.     procedure GotoPosition(Pos: Integer);
  33.   end;
  34.  
  35. var
  36.   Form1: TForm1;
  37.  
  38. implementation
  39.  
  40. {$R *.lfm}
  41.  
  42. { TForm1 }
  43.  
  44. procedure TForm1.lbeResultMaxEditingDone(Sender: TObject);
  45. var
  46.   NewValue: Integer;
  47. begin
  48.   if not(TryStrToInt(lbeResultMax.Text, NewValue)) then
  49.   begin
  50.     lbeResultMax.Text := IntToStr(FResultMax);
  51.     Exit;
  52.   end;
  53.   if NewValue <= FResultMin then
  54.   begin
  55.     lbeResultMax.Text := IntToStr(FResultMax);
  56.     Exit;
  57.   end;
  58.   FResultMax := NewValue;
  59.   CalculatePosition;
  60. end;
  61.  
  62. procedure TForm1.lbeResultMinEditingDone(Sender: TObject);
  63. var
  64.   NewValue: Integer;
  65. begin
  66.   if not(TryStrToInt(lbeResultMin.Text, NewValue)) then
  67.   begin
  68.     lbeResultMin.Text := IntToStr(FResultMin);
  69.     Exit;
  70.   end;
  71.   if NewValue >= FResultMax then
  72.   begin
  73.     lbeResultMin.Text := IntToStr(FResultMin);
  74.     Exit;
  75.   end;
  76.   FResultMin := NewValue;
  77.   CalculatePosition;
  78. end;
  79.  
  80. procedure TForm1.lbeGotoEditingDone(Sender: TObject);
  81. var
  82.   NewValue: Integer;
  83. begin
  84.   if not(TryStrToInt(lbeGoto.Text, NewValue)) then Exit;
  85.   if (NewValue < FResultMin) or (NewValue > FResultMax) then Exit;
  86.   lbeGoto.Text := '';
  87.   GotoPosition(NewValue);
  88. end;
  89.  
  90. procedure TForm1.Image1Click(Sender: TObject);
  91. var
  92.   NewPos:TPoint;
  93. begin
  94.   NewPos      := ScreenToClient(Mouse.CursorPos);
  95.   Image2.Left := NewPos.X - (Image2.Width div 2);
  96.   CalculatePosition;
  97. end;
  98.  
  99. procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  100. var
  101.   AllowedMin,
  102.   AllowedMax : Integer;
  103. begin
  104.  
  105.   if not(ssLeft in Shift) then Exit;
  106.  
  107.   AllowedMin := Image1.Left;
  108.   AllowedMax := Image1.Left + Image1.Width - Image2.Width;
  109.  
  110.   Image2.Left := Image2.Left + X - (Image2.Width div 2);
  111.   if Image2.Left < AllowedMin then Image2.Left := AllowedMin;
  112.   if Image2.Left > AllowedMax then Image2.Left := AllowedMax;
  113.  
  114.   CalculatePosition;
  115.  
  116. end;
  117.  
  118. procedure TForm1.FormCreate(Sender: TObject);
  119. begin
  120.   FResultMin := StrToInt(lbeResultMin.Text);
  121.   FResultMax := StrToInt(lbeResultMax.Text);
  122. end;
  123.  
  124. procedure TForm1.CalculatePosition;
  125. var
  126.   Result: Integer;
  127. begin
  128.   Result := ((FResultMax-FResultMin) *
  129.             (Image2.Left-Image1.Left) div
  130.             (Image1.Width-Image2.Width)) + FResultMin;
  131.   Label1.Caption := Result.ToString;
  132. end;
  133.  
  134. procedure TForm1.GotoPosition(Pos: Integer);
  135. begin
  136.   Image2.Left := Round((Pos-FResultMin) * (Image1.Width-Image2.Width) /
  137.                  (FResultMax-FResultMin) + Image1.Left);
  138.   Label1.Caption := Pos.ToString;
  139. end;
  140.  
  141. end.

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: TPanel slider position
« Reply #14 on: December 03, 2023, 04:45:31 pm »
I meant how to calculate the progress of the bar with automatic progress, e.g. time elapsed, as is the case in players.

Code: Pascal  [Select][+][-]
  1. Image2.Left := AParam * (Image1.Width -image2.Width div 2) div ResultMax;

AParam(current position)

the above line of code counts the time correctly, but at startup it goes back to the left side, so I would like to correct it
I am attaching a screenshot video of the bar


 

TinyPortal © 2005-2018