【发布时间】:2017-07-01 14:39:05
【问题描述】:
我遇到了一些小问题。
想象两件事:表格,应该被覆盖 - Cover-Form;以及涵盖 Cover-Form - Tiles 的表格。
我的主要目标是用 Tiles 覆盖我的 Cover-Form。所以它看起来像瓷砖。我用下图说明这个想法
黄色是封面形式,棕色形式 - 瓷砖。在此图像中,您可以看到表单彼此之间的位置太近 - 它们之间没有可用空间。这就是我需要的。
但是当我尝试达到相同的效果时,我得到的结果并不令人满意。如下图所示
第二个图像在最后一个图块之后有一个偏移量。这是由于表格大小不同而发生的。我不确切知道我的 Cover-Form 的宽度。我简单地将 Cover-Form 的整个宽度分为三个部分。但是如果 Cover-Form 有宽度,例如 173 像素,我的每个 Tiles 的宽度将等于 173/3=57.6 像素,这将四舍五入到 58,但 58*3=174 很糟糕。
下面的代码运行情况与第二张图片一样。
type
TTileArray = Array of Array of TPoint;
// This routine comes here from David's answer below and were changed by me
procedure EvenlySpacedTiles(PixelCountH, PixelCountV, TileCount: Integer; var ArrayOut: TTileArray);
var
X: Integer;
Y: Integer;
OldH: Integer;
OldV: Integer;
OldCount: Integer;
OldCount1: Integer;
TempInt: Integer;
begin
if (PixelCountH) or (PixelCountV) or(TileCount) = 0 then
Exit;
OldH := PixelCountH;
OldCount1 := TileCount;
for X:=Low(ArrayOut) to High(ArrayOut) do
begin
OldV := PixelCountV;
OldCount := TileCount;
TempInt := OldH div OldCount1;
Dec(OldH, TempInt);
Dec(OldCount1);
for Y:=Low(ArrayOut) to High(ArrayOut) do
begin
ArrayOut[X, Y] := Point(TempInt, OldV div OldCount);
Dec(OldV, ArrayOut[X, Y].Y);
Dec(OldCount);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
F: TForm;
P: TForm;
Delta: Integer;
PrevLeft: Integer;
PrevTop: Integer;
X:Integer;
Y: Integer;
Arr: TTileArray;
IncLeft: Integer;
begin
Delta := 3;
F := TForm.Create(Application);
F.BorderStyle := Forms.bsNone;
F.SetBounds(0, 0, 173, 115);
F.Position := poDesktopCenter;
F.Color := $11DFEE;
F.Show;
SetLength(Arr, Delta, Delta);
EvenlySpacedTiles(F.Width, F.Height, Delta, Arr);
PrevLeft := F.Left;
PrevTop := F.Top;
IncLeft := 0;
for X:=Low(Arr) to High(Arr) do
begin
PrevTop := F.Top;
Inc(PrevLeft, IncLeft);
for Y:=Low(Arr) to High(Arr) do
begin
P := TForm.Create(Application);
P.FormStyle := fsStayOnTop;
P.BorderStyle := Forms.bsNone;
P.Color := Random($FFFFFF);//clSkyBlue;
P.Show;
P.Width := Arr[X, Y].X;
P.Height := Arr[X, Y].Y;
P.Left := PrevLeft;
P.Top := PrevTop;
P.Canvas.Rectangle(P.ClientRect);
Inc(PrevTop, Arr[X, Y].y);
IncLeft := Arr[X, Y].X;
end;
end;
end;
所以我的问题是:如何独立于封面表单的宽度调整所有图块的宽度(每行 3 个)?
提前致谢。
已编辑
附言
我修改了上面的部分代码。现在,即使 Cover-Form 宽度非常小和非常大 - 从 67 像素起,它也能完美运行。到 1237 像素。
当然有办法改进这段代码,但主要目标已经实现。
我想我明天就能完成垂直瓷砖放置并在那里发布这部分。
在很多方面,大卫的评论让我知道如何做到这一点。谢谢你,大卫!
附言
我已经斜着阅读了大卫的第一条评论,所以我更新代码以另一种方式工作,但结果仍然不好。您可以在下面的图片中看到它。
第一个 Tile 有 57 像素。宽度;第二个 - 59 px。第三个瓷砖 - 只有 31 像素。
我只是不知道如何使用大卫评论中建议的算法正确放置瓷砖。
附言
还是没有结果。
右红线显示最后一个瓷砖的大尺寸。每个图块的宽度为 58 像素。
大卫写道:
173/3=58。 173-58=115。 115/2=58。 115-58=57。 57/1=57
我可以在现实生活中计算它,但我无法在代码中实现它。
源代码已更新。
P.S.S.S.S.
大卫的程序没有做它应该做的事情。下图说明了它。
第一个和第二个 Tile 之间有一个间隙,右侧的红线如上图所示。
P.S.S.S.S.S.
好了,此时我的任务的第一部分就完成了。第二个 - 添加更多的瓷砖,但我不确定我是否真的需要它们。我很感谢David Heffernan!他花了很多时间向我解释一些事情,而我不知道该怎么说他只是简单地说“非常感谢”。恐怕,我只能增加他的声誉并接受他的帖子作为答案。它真的很管用!
在图片上我们可以看到我需要的结果
【问题讨论】:
-
173 不能被 3 整除。因此,您不能对每列使用相同的宽度。而是这样做。从 Npx 像素开始。除以 Ncol,取整。将该值用于第 0 列。从 Npx 中减去该值,然后除以 Ncol-1。将该值四舍五入并用于第 1 列。重复直到用完像素和列。
-
另外,除非有充分的理由为了简洁而省略,否则您不会将每个图块实现为单独的表单。改用形状或其他更合适的东西。
-
@DavidHeffernan,你的意思是下一个情况,对吧?假设,我有宽度为 173 像素的 Cover-Form。我知道我应该每行放置三个 Tiles,所以我除以 173 / 3 = 57。这是每个 Tile 的宽度。然后我将 3 个 Tiles 乘以 57 得到 171。我知道 171 小于 173,根据这个事实我应该这样做:173 - 171 = 2。这是在第二个出现的最后一个 Tile 之后的大小位置图像,所以我只是增加最后一个 TIle 的宽度以完全适合 Cover-Form。你觉得这个方法怎么样?
-
@DNR,不幸的是,shapes 不是一个好的解决方案。
-
没有。完全按照我描述的方式去做。不需要乘法。您只需要消耗大量像素,并且对于每一列,尽可能均匀地消耗它们。最终你将没有任何东西可以消费。