【问题标题】:Delphi/Firemonkey make Listboxses sync scroll betterDelphi/Firemonkey 使 Listboxses 同步滚动更好
【发布时间】:2015-09-17 13:19:41
【问题描述】:

我有一种非常肮脏的方式让 7 个列表框同步滚动,它们都具有完全相同的高度,所以当我移动其中任何一个的位置时,其他 6 个也应该移动到该位置

我所做的是假设 Listbox1 被滚动并且我说 ViewportPositionChange() 被触发

Listbox2.ViewportPosition := NewViewportPosition;
Listbox3.ViewportPosition := NewViewportPosition;

这一切都有效,我只是将这段代码添加到每个 Listboxses ViewportPositionChange() 事件中,但它在 Andriod 上非常生涩且太慢,我仍然需要能够从任何一个列表框滚动,但没有办法提高滚动性能?

好吧,老实说,它并不是很慢,但您会感觉到它并不十分活泼,而且每个列表框都可以有很多列表框,每个列表框还可以有一些控件,并且这些控件中有更多控件,因此需要大量重新绘制我认为已经完成了,这就是让它变得不那么活泼的原因。

示例代码

首先在表单上放置一个 Gridpanel 布局,添加 6 个列并为每个列添加一个列表框,每个列表框代表一天,其中列表框 1 是星期一,也将这些对齐到客户端。

全局变量

private Glistbox : array[0..6] of TListBox;

在表单上创建

Glistbox[0] := ListBox1;
Glistbox[1] := ListBox2;
Glistbox[2] := ListBox3;
Glistbox[3] := ListBox4;
Glistbox[4] := ListBox5;
Glistbox[5] := ListBox6;
Glistbox[6] := ListBox7;

现在在每个列表框上 OnViewportPositionChange

//Note that this would be for Listbox1 so for listbox 2 it needs to be changed acordingly
ListBox2.ViewportPosition := NewViewportPosition;
ListBox3.ViewportPosition := NewViewportPosition;
ListBox4.ViewportPosition := NewViewportPosition;
ListBox5.ViewportPosition := NewViewportPosition;
ListBox6.ViewportPosition := NewViewportPosition;
ListBox7.ViewportPosition := NewViewportPosition;

然后添加一个按钮,代码如下:

 var
    mainlayout,item1,item2 : Tlayout;
    listboxitem : TListBoxItem;
    myrec,myrec2 : TRectangle;
    lbl1,lbl2 : TLabel;
    I: Integer;
begin
for I := 0 to 6 do
begin
    listboxitem := TListBoxItem.Create(nil);

    mainlayout := TLayout.Create(nil);
    mainlayout.Align := TAlignLayout.Client;
    mainlayout.Parent:= listboxitem;

    item1 := TLayout.Create(nil);
    item1.Align:= TAlignLayout.Left;
    item1.Parent := mainlayout;

    item2 := TLayout.Create(nil);
    item2.Align:= TAlignLayout.Right;
    item2.Parent := mainlayout;

    myrec := TRectangle.Create(nil);
    myrec.Align := TAlignLayout.Client;
    myrec.Parent := item1;

    myrec2 := TRectangle.Create(nil);
    myrec2.Align := TAlignLayout.Client;
    myrec2.Parent := item2;

    lbl1 := TLabel.Create(nil);
    lbl1.Align := TAlignLayout.Client;
    lbl1.TextAlign := TTextAlign.Center;
    lbl1.Text := '1';
    myrec.AddObject(lbl1);

    lbl2 := TLabel.Create(nil);
    lbl2.Align := TAlignLayout.Client;
    lbl2.TextAlign := TTextAlign.Center;
    lbl2.Text := '2';
    myrec2.AddObject(lbl2);

    Glistbox[I].AddObject(listboxitem);
    item2.Width:= mainlayout.Width/2;
end;

listboxitem 中有时可能会有更多控件,但通常我认为这是常态,现在添加一些项目并尝试滚动

【问题讨论】:

  • 您是否考虑过使用七列网格控件?
  • 不幸的是,在不更改太多其他代码的情况下,我已经陷入了太深的困境,无法更改为网格控件,就像我说的那样,它并不活泼,但现在可以使用
  • 换句话说,您已经决定不想考虑其他选项。在这种情况下,为什么要问这个问题。至少要诚实。说你不能面对改变设计,但有一些神奇的开关让你的应用程序超级时髦。喜欢Application.AwesomeScrolling := True
  • 我愿意更改设计,但我想先知道是否有一些有用的做法可以尝试,例如在更改设计之前添加列表框项目时使用 BeginUpdate 和 EndUpdate,基本上任何基本的我可能错过了可以改进当前设计的方法,如果我唯一的选择是网格控件,那很好,它会在某个阶段更改为那个
  • 很公平。我认为如果我们可以重现该行为,您将更容易获得帮助。就目前而言,我们必须尝试根据问题中的松散描述从头开始构建您的应用程序。这并不吸引人,因为我们必须投入大量时间,但不能保证最终会得到您的应用。

标签: delphi firemonkey


【解决方案1】:

FMX TListBox 有很多开销,因为每个列表框项基本上都是插入滚动框的样式组件。这有利于灵活性,但不利于速度。

在 Windows 和 OSX 中,诸如 ScrollWindowEx 或 NSView.scrollRect + NSView.setNeedsDisplayInRect 之类的函数可以通过滚动窗口的一部分而不发出绘制消息来帮助提高性能。因此,您只需使列表框的一部分无效。我可以想象 Android 也有类似的东西。但是您可能必须修补 FMX 才能使用它。这可以稍微提高性能,但仍然不是获得出色性能的神奇开关。类似的方法是将滚动框的内容缓存在位图中,然后在滚动时将部分位图复制到屏幕上。

如果您需要非常好的列表框性能,那么您需要开发自己的列表框,该列表框已针对速度进行了优化。为了获得所需的性能,我必须为我的应用程序的 OSX 版本执行此操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多