Delphi - 图像在桌面坐标内随机移动
Delphi - Image move randomly inside desktop coordinates
我想创建一个小应用程序,它可以将图像平滑地移动到桌面坐标中。
我想知道如何限制图像保留在桌面内?
我试过那样移动图像:
procedure TForm1.Timer1Timer(Sender: TObject);
Var
X, Y :Integer;
begin
X:= random(2+1);
Y:= random(2+1);
Image1.Left:= Image1.Left + X;
Image1.Top:= Image1.Top + Y;
Image1.Refresh;
end;
感谢任何帮助。
谢谢。
您的图像是放在 Windows 桌面上还是放在您 TForm1
上?我猜是后者。所以你必须关心 WINDOW 大小,而不是桌面大小。
type TForm1=class(TForm)
....
private
ImageMovesLeft, ImageMovesUp: Boolean;
end;
.....
procedure TForm1.Timer1Timer(Sender: TObject);
Var
dX, dY, NewLeft, NewTop :Integer;
FormSize: TRect;
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - Image1.Height - 1;
FormSize.Right := FormSize.Right - Image1.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImageMovesLeft then dX := -dX;
If ImageMovesUp then dY := -dY;
NewLeft := Image1.Left + dX;
NewTop := Image1.Top + dY;
if ( NewTop >= FormSize.Top ) and ( NewTop <= FormSize.Bottom ) then begin
Image1.Top := NewTop; // we fit into the allowed box
end else begin
ImageMovesUp := not ImageMovesUp; // we did not fit and have to bounce back
end;
if ( NewLeft >= FormSize.Left ) and ( NewLeft <= FormSize.Right ) then begin
Image1.Left := NewLeft; // we fit into the allowed box
end else begin
ImageMovesLeft := not ImageMovesLeft; // we did not fit and have to bounce back
end;
end;
PS。在不太可能的情况下,您确实需要 Windows DESKTOP 坐标,而不是您的表单坐标,您可以在
处获取它们
http://docwiki.embarcadero.com/Libraries/XE7/en/Vcl.Forms.TScreen.DesktopRect
但是要使用该信息,您必须解决另一个问题 - 如何将 Image1
放在桌面上而不是表格上,这对您来说要复杂得多。所以我不认为你真的是指桌面....
更新。上面的代码虽然非常简单易懂,但它几乎没有做出正确工作的隐含假设。这些假设是:
- window(form) 大小是一次性固定的,永远不会改变大小。
- 图片框大小是一次性固定的,永远不会调整。
- window 在两个维度上都比图像框大。
- 只有我们的程序可以移动图像框,没有别的可以移动它。
鉴于这些假设(许多年前对于固定屏幕尺寸的计算机来说是自然的),没有必要分析移动物体是太左还是太右、太高或太低。只有新坐标正确与否才重要 - 如果它不再正确,那么 "bouncing" - 反转方向而不看它是哪个 - 就足够了。但是,例如,如果用户可以突然调整 window 的大小并使其变得如此之小以至于图像框会落在它的外面 - 那么这种方法将无限切换方向,因为坐标总是不正确给那些非常小的改动"smooth"动作允许有。
为了适应几何中可能发生的突然和大的变化,可以采用多种方法,但最简单的方法是进行两项更改:区分两种错误坐标的情况(太小或太大现在会不同的情况),并在需要时将图像即时跳转到允许的框中,即使跳转很大且不平滑。
procedure TForm1.Timer1Timer(Sender: TObject);
var
dX, dY, NewLeft, NewTop :Integer;
FormSize: TRect;
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - Image1.Height - 1;
FormSize.Right := FormSize.Right - Image1.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImageMovesLeft then dX := -dX;
If ImageMovesUp then dY := -dY;
NewLeft := Image1.Left + dX;
NewTop := Image1.Top + dY;
if NewLeft > FormSize.Right then begin
ImageMovesLeft := True;
NewLeft := FormSize.Right;
end;
if NewLeft < FormSize.Left then begin
ImageMovesLeft := False;
NewLeft := FormSize.Left;
end;
if NewTop > FormSize.Bottom then begin
ImageMovesUp := True;
NewTop := FormSize.Bottom;
end;
if NewTop < FormSize.Top then begin
ImageMovesUp := False;
NewTop := FormSize.Top;
end;
Image1.Top := NewTop;
Image1.Left := NewLeft;
end;
更新。几个控件在移动。
type TControlledObject = record
obj: TControl;
MovesLeft, MovesUp: Boolean;
end;
type TForm1=class(TForm)
....
private
images: array of TControlledObject;
end;
procedure TForm1.FormShow(....);
begin
SetLength(images, 3);
with images[0] do begin
obj := Self.Image1;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
with images[1] do begin
obj := Self.Image2;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
with images[2] do begin
obj := Self.Image3;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer
begin
for i := 0 to Length(images)-1 do
MoveImage(images[i]);
end;
procedure TForm1.MoveImage(var ImgRec: TControlledObject);
var .....
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - ImgRec.obj.Height - 1;
FormSize.Right := FormSize.Right - ImgRec.obj.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImgRec.MovesLeft then dX := -dX;
If ImgRec.MovesUp then dY := -dY;
.....等等。完成从一到多的转换作为你的家庭任务。
我想创建一个小应用程序,它可以将图像平滑地移动到桌面坐标中。 我想知道如何限制图像保留在桌面内? 我试过那样移动图像:
procedure TForm1.Timer1Timer(Sender: TObject);
Var
X, Y :Integer;
begin
X:= random(2+1);
Y:= random(2+1);
Image1.Left:= Image1.Left + X;
Image1.Top:= Image1.Top + Y;
Image1.Refresh;
end;
感谢任何帮助。
谢谢。
您的图像是放在 Windows 桌面上还是放在您 TForm1
上?我猜是后者。所以你必须关心 WINDOW 大小,而不是桌面大小。
type TForm1=class(TForm)
....
private
ImageMovesLeft, ImageMovesUp: Boolean;
end;
.....
procedure TForm1.Timer1Timer(Sender: TObject);
Var
dX, dY, NewLeft, NewTop :Integer;
FormSize: TRect;
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - Image1.Height - 1;
FormSize.Right := FormSize.Right - Image1.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImageMovesLeft then dX := -dX;
If ImageMovesUp then dY := -dY;
NewLeft := Image1.Left + dX;
NewTop := Image1.Top + dY;
if ( NewTop >= FormSize.Top ) and ( NewTop <= FormSize.Bottom ) then begin
Image1.Top := NewTop; // we fit into the allowed box
end else begin
ImageMovesUp := not ImageMovesUp; // we did not fit and have to bounce back
end;
if ( NewLeft >= FormSize.Left ) and ( NewLeft <= FormSize.Right ) then begin
Image1.Left := NewLeft; // we fit into the allowed box
end else begin
ImageMovesLeft := not ImageMovesLeft; // we did not fit and have to bounce back
end;
end;
PS。在不太可能的情况下,您确实需要 Windows DESKTOP 坐标,而不是您的表单坐标,您可以在
处获取它们http://docwiki.embarcadero.com/Libraries/XE7/en/Vcl.Forms.TScreen.DesktopRect
但是要使用该信息,您必须解决另一个问题 - 如何将 Image1
放在桌面上而不是表格上,这对您来说要复杂得多。所以我不认为你真的是指桌面....
更新。上面的代码虽然非常简单易懂,但它几乎没有做出正确工作的隐含假设。这些假设是:
- window(form) 大小是一次性固定的,永远不会改变大小。
- 图片框大小是一次性固定的,永远不会调整。
- window 在两个维度上都比图像框大。
- 只有我们的程序可以移动图像框,没有别的可以移动它。
鉴于这些假设(许多年前对于固定屏幕尺寸的计算机来说是自然的),没有必要分析移动物体是太左还是太右、太高或太低。只有新坐标正确与否才重要 - 如果它不再正确,那么 "bouncing" - 反转方向而不看它是哪个 - 就足够了。但是,例如,如果用户可以突然调整 window 的大小并使其变得如此之小以至于图像框会落在它的外面 - 那么这种方法将无限切换方向,因为坐标总是不正确给那些非常小的改动"smooth"动作允许有。
为了适应几何中可能发生的突然和大的变化,可以采用多种方法,但最简单的方法是进行两项更改:区分两种错误坐标的情况(太小或太大现在会不同的情况),并在需要时将图像即时跳转到允许的框中,即使跳转很大且不平滑。
procedure TForm1.Timer1Timer(Sender: TObject);
var
dX, dY, NewLeft, NewTop :Integer;
FormSize: TRect;
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - Image1.Height - 1;
FormSize.Right := FormSize.Right - Image1.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImageMovesLeft then dX := -dX;
If ImageMovesUp then dY := -dY;
NewLeft := Image1.Left + dX;
NewTop := Image1.Top + dY;
if NewLeft > FormSize.Right then begin
ImageMovesLeft := True;
NewLeft := FormSize.Right;
end;
if NewLeft < FormSize.Left then begin
ImageMovesLeft := False;
NewLeft := FormSize.Left;
end;
if NewTop > FormSize.Bottom then begin
ImageMovesUp := True;
NewTop := FormSize.Bottom;
end;
if NewTop < FormSize.Top then begin
ImageMovesUp := False;
NewTop := FormSize.Top;
end;
Image1.Top := NewTop;
Image1.Left := NewLeft;
end;
更新。几个控件在移动。
type TControlledObject = record
obj: TControl;
MovesLeft, MovesUp: Boolean;
end;
type TForm1=class(TForm)
....
private
images: array of TControlledObject;
end;
procedure TForm1.FormShow(....);
begin
SetLength(images, 3);
with images[0] do begin
obj := Self.Image1;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
with images[1] do begin
obj := Self.Image2;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
with images[2] do begin
obj := Self.Image3;
MovesLeft := random >= 0.5;
MovesUp := random >= 0.5;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: Integer
begin
for i := 0 to Length(images)-1 do
MoveImage(images[i]);
end;
procedure TForm1.MoveImage(var ImgRec: TControlledObject);
var .....
begin
dX := random(2+1); // did you really mean "random(3)" or "1+random(2)" ???
dY := random(2+1);
FormSize := Self.ClientRect;
FormSize.Bottom := FormSize.Bottom - ImgRec.obj.Height - 1;
FormSize.Right := FormSize.Right - ImgRec.obj.Width - 1;
// now we have the "box" in which the Image's topleft corner must be
If ImgRec.MovesLeft then dX := -dX;
If ImgRec.MovesUp then dY := -dY;
.....等等。完成从一到多的转换作为你的家庭任务。