ScaleBy + 轨迹栏

ScaleBy + trackbar

我需要帮助来使用轨迹栏实现控件缩放(通过 ScaleBy 方法)。

这是我的轨迹栏 OnChange 事件,但它不能完美地工作:

procedure TMainForm.tbScaleChange(Sender: TObject);
begin
  if tbScale.Tag = 0 then
  begin
    // this section is to make trackbar's step = 5
    tbScale.Tag := 1;
    if tbScale.Position mod 5 <> 0 then
      tbScale.Position := 5 * ((tbScale.Position + 5 div 2) div 5);
    tbScale.Tag := 0;

    // in FtbScalePrevPos form variable I keep previous trackbar position
    if FtbScalePrevPos > tbScale.Position then
      someControl.ScaleBy(100, 105)
    else if FtbScalePrevPos < tbScale.Position then
      someControl.ScaleBy(105, 100);
    FtbScalePrevPos := tbScale.Position;
  end;
end;

缩放以上控件后,移动轨迹栏的尺寸增长过快。

编辑: 我的轨迹栏有 Min = 50,Max = 200,这些值是以百分比表示的比例因子。 increasing/decreasing tbScale.Position by 5 的代码有点复杂,但工作正常并且与我的问题的根源无关。问题是找到将根据轨迹栏位置计算适当比例因子的函数。 在将 tbScale.Position 直接传递给 ScaleBy 方法的幼稚方法中,如果我将轨迹栏移动到 150(缩放因子 1.5)然后移动到 200(因子 2),我的控件将不会像我希望的那样缩放 2,而是缩放 3 (1.5*2)。简单的解决方案是保存 someControl 的初始尺寸,然后将它们与计算出的比例因子一起使用。不幸的是,在我的例子中,someControl 是 TTabSheet,事实上我想扩展它的许多子控件。

考虑对您的代码进行以下更改:

  1. 不要在 OnChange 事件中更改 tbScale.Position,使用 局部临时变量代替。实际上,你甚至不需要 暂时的。
  2. 因为第1点,你可以删除处理的代码 tbScale.Tag
  3. 使 tbScale 步骤 = 5 不是必需的,您只是在使用它 用于与之前的值进行比较 (<, >)。

因此您的代码被简化为以下内容:

procedure TForm22.tbScaleChange(Sender: TObject);
begin
  if FtbScalePrevPos > tbScale.Position then
    Button1.ScaleBy(100, 105)
  else if FtbScalePrevPos < tbScale.Position then
    Button1.ScaleBy(105, 100);
  FtbScalePrevPos := tbScale.Position;
end;

如果 incrementing/decrementing 每步 5% 走得太快,将 105 减少为 103。

TTrackBar 默认有 Min= 0Max=10。如果您希望能够减小缩放控件的大小,请设置例如Min := -10。如果要增加步数,调整MinMax.


在附加信息后编辑

我现在明白问题出在哪里了(我认为)。在之前,尺寸变化是渐进的,您正在寻找线性变化。

我仍然坚持认为,您使用 tbScale 值进行的计算可以替换为分配最小值、最大值和初始位置第 5 个较小的值,并在 OnChange 过程中乘以 5。

tbScale2 的范围为 10..40(而不是 50..200),初始位置为 20(而不是 100),FtbScale2PrevPos 的初始位置为 100,以下将操作从渐进式更改为线性。

procedure TForm22.FormCreate(Sender: TObject);
begin
  FtbScale2PrevPos := 100;
end;

procedure TForm22.tbScale2Change(Sender: TObject);
begin
  Button1.ScaleBy(tbScale2.Position * 5, FtbScale2PrevPos);

  FtbScale2PrevPos := tbScale2.Position * 5;
end;