2
votes

I am writing 2-3 Trees application in Lazarus for my school project.

Everything's done, now playing with GUI (I get the same number of points for good GUI as I do for a good etc. Insert function, which is weird but nvm).

When I have like 10+ nodes in the tree, my 300*200 image size just isn't large enough.

I would like to have an TImage component which would be like 300*200 on the TForm, but it would be like 10000 * 10000 really and you could scroll in it.

Is it even possible?

Thanks

EDIT TO MAKE THE QUESTION CLEARER

  1. A 2-3 Tree is a data structure. When drawn on a paper to see how it works, it looks like this http://www.cosc.canterbury.ac.nz/research/RG/alg/tree23.gif

  2. As a real noobie in lazarus/delphi (have to do it in lazarus) a use this code to draw it (even if I doubt u need it to answer my question):

    procedure TStrom.Paint(Image: TImage);
    

    var C: TCanvas;

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

    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. The draw function works well, but some (most) of the nodes at the height of 3+ are drawn on other nodes, so it looks bad. The node is sitting on another node and is not 20 pixels next to it.

  4. I thought I'd make the image where the tree is painted real big, but it would be in a small "panel". Like this: the TImage would really be 1000*1000, but in the form you could see only a little part of it. In this part there'd be horizontal and vertical scrollbars, so you could scroll through the image and see what's painted in the sections. (Like when you scroll through a web browser to see the bottom of the page :) )

  5. We are not permitted to use any other code, just built in lazarus components. (nor are we permitted to create new components -> have no idea why)

  6. While I'm still curious about how this could be done, it's no longer necessary for my application ( installed a second monitor to see if it'd help and it wouldn't, so I guess I'd dig through my paint method a bit :-) )

2
What's a "2-3 Trees application"? How is the tree and the image related?Sertac Akyuz
@Sertac, I think we can assume that a 2-3 tree application is an application that does something with 2-3 trees. I think we can also assume that an image is being used to display the tree on the screen. Neither is crucial to understanding the question, though, which simply asks how to introduce scrolling when an image is too big to fit on the screen. The nature of the image is irrelevant.Rob Kennedy
That would mean using a Bitmap with about 400 MB. You should better paint on a e.g. Paintbox. You would be able to use SetWorldTransform, alway painting the same with different clipping.bummi
@Rob - One could maybe suggest using a treeview instead of an image - which have built-in scrolling capability, should the nature of the problem had been known.Sertac Akyuz

2 Answers

3
votes

Your edit makes it more clear that you want to draw a schematic like the last tree in the example you link to.

From your code I understand that you are drawing all nodes, childs and leaves, onto a single canvas resulting in one large image/bitmap. Now, how to display only part of that large image with scroll bars next to it?

The obvious choice would be to place a TPaintBox on a TScrollBox. I do not know the default suite of components in Lazarus, but I expect both of them to be present. Give the paint box a size equal to the bounds of your visual tree and you're set: scroll bars will be shown automatically.

The paint box has an OnPaint event in which you do your paint work by drawing to PaintBox.Canvas. To optimize this, you could limit your drawing to PaintBox.Canvas.ClipRect (the part of the paint box that is visible within the scroll box), but I suspect that to be difficult, since you already have difficulty with computing the right distance between adjacent nodes. (About that: I expect the maximum width and height of the total tree to be a function of the total depth, but I could easily be mistaken.)

If Lazarus does not have a TPaintBox, then use a TImage which also has a Canvas property. Downside is that TImage "stores" all drawing operations in one big internal bitmap, which could raise memory or resource issues when your tree expands too much.

1
votes

Could all images be combined to one large image? If so, then maybe this component answers your question.

It is a descendant of TGraphicControl, capable of animated zooming. Zoom in on a part of the graphic by dragging a selection rectangle, zoom out the whole graphic by double clicking it. Shoot if you need help to update it to be able to perform pan operations.