【问题标题】:Scrolling TImage horizontally or vertically水平或垂直滚动​​ TImage
【发布时间】:2012-12-29 23:59:15
【问题描述】:

我正在为我的学校项目在 Lazarus 编写 2-3 树应用程序。

一切都完成了,现在开始玩 GUI(好的 GUI 获得的分数与获得好的等值相同。插入功能,这很奇怪,但 nvm)。

当我在树中有 10 多个节点时,我的 300*200 图像尺寸就不够大了。

我想要一个 TImage 组件,它在 TForm 上是 300*200,但实际上是 10000 * 10000,你可以在其中滚动。

有可能吗?

谢谢

编辑使问题更清楚

  1. 2-3 树是一种数据结构。在纸上绘制以查看其工作原理时,它看起来像这样http://www.cosc.canterbury.ac.nz/research/RG/alg/tree23.gif

  2. 作为 lazarus/delphi 中的真正菜鸟(必须在 lazarus 中进行)使用此代码来绘制它(即使我怀疑你需要它来回答我的问题):

    procedure TStrom.Paint(Image: TImage);
    

    变量 C:TCanvas;

    procedure Paint1(V: TNode; Width, X, Y: integer); 开始

    if V.L <> nil then    //left child
    begin
      C.MoveTo(X, Y);
      C.LineTo(X - Width div 3, Y + 50);
      Paint1(V.L, Width div 3, X - Width div 3, Y + 50);
    end;
    
    if V.S <> nil then    //middle child 
    begin
      C.MoveTo(X, Y);
      C.LineTo(X + Width div 3, Y + 50);
      Paint1(V.S, Width div 3, X + Width div 3, Y + 50);
    end;
    
    if V.P <> nil then     //right child
    begin
      C.MoveTo(X, Y);
      C.LineTo(X + Width div 3 + Width div 3, Y + 50);
      Paint1(V.P, Width div 3, X + Width div 3 + Sirka div 3, Y + 50);
    end;
    
    if V.isLeaf then
    begin
      C.Ellipse(X - 15, Y - 15, X + 15, Y + 15);
      C.TextOut(X - 3, Y - 8, IntToStr(V.Info1));
    end
    else
    begin
      C.Rectangle(X - 15, Y - 15, X + 15, Y + 15);
      C.TextOut(X - 7, Y - 8, IntToStr(V.Info1));
      C.Rectangle(X + 15, Y - 15, X + 50, Y + 15);
      if V.Info2 <> 0 then
        C.TextOut(X + 27, Y - 8, IntToStr(V.Info2));
    end;
    
  3. draw函数效果很好,但是3+高度的部分(大部分)节点被绘制在其他节点上,所以看起来很糟糕。该节点位于另一个节点上,并且在它旁边不是 20 像素。

  4. 我想我应该把树画得很大的图像,但它会在一个小的“面板”中。像这样:TImage 实际上是 1000*1000,但在表格中你只能看到它的一小部分。在这部分中会有水平和垂直滚动条,因此您可以滚动图像并查看部分中绘制的内容。 (就像你在浏览器中滚动查看页面底部时一样:))

  5. 我们不允许使用任何其他代码,只能使用内置的 lazarus 组件。 (我们也不允许创建新组件 -> 不知道为什么)

  6. 1234563稍微研究一下我的绘画方法:-))

【问题讨论】:

  • 什么是“2-3 树应用程序”?树和图像有什么关系?
  • @Sertac,我认为我们可以假设 2-3 树应用程序是使用 2-3 树做某事的应用程序。我认为我们也可以假设正在使用图像在屏幕上显示树。但是,这对于理解这个问题都不是至关重要的,它只是询问当图像太大而无法在屏幕上显示时如何引入滚动。图像的性质无关紧要。
  • 这意味着使用大约 400 MB 的位图。你应该更好地画在例如油漆盒。您将能够使用 SetWorldTransform,始终使用不同的剪辑绘制相同的内容。
  • @Rob - 如果已经知道问题的性质,可以建议使用树视图而不是图像 - 它具有内置滚动功能。

标签: delphi pascal lazarus


【解决方案1】:

您的编辑更清楚地表明您想要绘制类似于example you link to 中最后一棵树的示意图。

从您的代码中,我了解到您正在将所有节点、子节点和叶子绘制到单个画布上,从而生成一个大图像/位图。现在,如何只显示大图像的一部分,旁边有滚动条?

显而易见的选择是将TPaintBox 放在TScrollBox 上。我不知道 Lazarus 中的默认组件套件,但我希望它们都存在。将绘制框的大小设置为与您的可视化树的边界相同,然后您就设置好了:滚动条将自动显示。

绘画框有一个OnPaint 事件,您可以在其中通过向PaintBox.Canvas 绘画来完成绘画工作。为了优化这一点,您可以将绘图限制为PaintBox.Canvas.ClipRect(在滚动框中可见的油漆框部分),但我怀疑这很困难,因为您已经难以计算相邻节点之间的正确距离. (关于那个:我希望总树的最大宽度和高度是总深度的函数,但我很容易弄错。)

如果 Lazarus 没有TPaintBox,则使用TImage,它也有Canvas 属性。缺点是 TImage 将所有绘图操作“存储”在一个大的内部位图中,当你的树扩展过多时,这可能会引发内存或资源问题。

【讨论】:

    【解决方案2】:

    是否可以将所有图像合并为一张大图像?如果是这样,那么this component 可能会回答您的问题。

    它是TGraphicControl 的后代,能够进行动画缩放。通过拖动选择矩形放大图形的一部分,通过双击缩小整个图形。如果您需要帮助更新它以便能够执行平移操作,请拍摄。

    【讨论】:

    • 这很顺利,虽然它不能完全回答我的问题,但值得加 1 :)
    猜你喜欢
    • 2021-11-13
    • 2014-01-09
    • 1970-01-01
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2013-05-22
    • 1970-01-01
    相关资源
    最近更新 更多