Placing Canvas/Viewport/Container (?) in TRootEmbeddedCanvas

Hello Rooters,

I have a GUI in table layout (default 2 rows x 2 columns) with a TRootEmbeddedCanvas in each frame cell and I want to accomplish the following feat:

When the main frame is resized, the TRootEmbeddedCanvases are supposed to expand in x and y to fill out their frame cells, but the actual TCanvas with its content is supposed to keep its aspect ratio when expanding and shall be placed in the center of the respective TRootEmbeddedCanvases like this:

These images have been photoshopped to represent the desired behavior.

As you can see in the attached minimal example, I have been fiddling around with TRootEmbeddedCanvas, TRootEmbeddedCanvas->GetCanvas(), TRootEmbeddedCanvas->GetContainer(), TRootEmbeddedCanvas->GetViewPort(), and TRootEmbeddedCanvas->GetViewPort()->GetContainer() - all with different background colors for visualization, but I have not been able to solve the issue. As a result I am now completely confused about the different objects and their purpose.

Any helpful input on the situation?

Cheers (112 KB)


And what about creating a TPad in each TCanvas and then moving/resizing this TPad? (since the TCanvas is taking the whole space inside the TRootEmbeddedCanvas)

Cheers, Bertrand.


well, this could probably work even though it would mean a lot of code refactoring for the GUI framework I’m dealing with.

Anyway, I am handling medical images which always have to be displayed with correct image and pixel dimensions, so user resize of the pad has to be prevented by all means. If I use pad->SetEditable(kFALSE), however, I throw away the possiblility of placing/dragging draw objects on top of the image for pixel analysis making the program useless.

Is there a way, to prevent user move/resize of the pad while retaining the “editableness” of it with respect to other draw objects?

If not I have to stay with the original question…


OK, then you have to play with layout and compute the ratio yourself. I’ll try to come with an example as soon as I have some time and let you know.

Cheers, Bertrand.

Thanks Bertrand!

Attached you find an experimental version which might give you a start. It’s basically how far I took the TPad approach using the canvas’ original pad instead of an additional one.

It is working fine when zooming/unzooming the image in canvas 1 (the ellipse does not scale properly yet), but it is not working correctly when resizing the GUI. For some reason the canvas background remains white instead of black in this case - no matter what I do. (Note: The canvas background has to be black for medical images so the radiologists perception of the gray values is not affected.)


PS: If we can’t figure it out, I might have to return to the approach from thread
[url]Handle click on a TGCompositeFrame
with consists of resizing the whole background frame and embedded canvas. This leads to other issues, however, which I would be happy to avoid. (113 KB)

Hi Greg,

Here are the modified MyGui.h and MyGui.cxx. A few comments:
[li] You must not use a class version for the GUI elements. For example: ClassDef(MyMainFrame, 0))[/li]
[li] To solve the black background issue, the solution I found is to use an extra Pad (I will ask our graphics expert tomorrow why this is needed…)[/li]
[li] It is much simpler to use: Connect("CloseWindow()", "TApplication", gApplication, "Terminate()"); and Connect("ProcessedConfigure(Event_t*)", "MyMainFrame", this, "GUIResized()");[/li]
[li] For the rest, I’ll let you take a look at the code and ask if you have any question.[/li][/ul]
Note that now you may try to use fImg->SetConstRatio(true);and move/resize the extra pad instead of the image… (I didn’t try myself)

Cheers, Bertrand.
MyGui.cxx (5.67 KB)
MyGui.h (1.34 KB)


thanks for the comments! It works pretty well with a few modifications. I’m still very interested, however, whether there is a solution without the extra pad.
[li]CloseWindow() / Terminate(): Good to know. I usually use a more complex “Close()” function though involving a “Really quit?” message box.[/li]
[li]fImg->SetConstRatio(true): In case of medical images, pixel height and width can differ. From what I see TImage treats them equal, so I have to set fConstRatio false and manually stretch the image to have the correct pixel aspect ratio. This is actually handled in the code example, except here I set wPix = hPix = 1.[/li]
[li]After playing around with the resizing for a bit I realized that deleting the frame is a bad idea, it frequently causes a segfault in TPad::Clear().[/li]
[li]The canvas aspect ratio relates to the actual canvas, not the pad. Mixing it up will occasionally produce false resize parameters.[/li]
[li]Also, I removed a few seemingly unnecessary pad->Update().[/li][/ul]
I attached the current version for future reference.

MyGui.cxx (5.52 KB)

Thanks again, Bertrand, based on your solution I was finally able to accompolish what I was looking for!

Two more things were required:
[li]Overwriting the TASImage::Draw() function in MyTASImage and removing the part where the TFrame is drawn keeps the user from manually resizing the image.[/li]
[li]The image is drawn inside a custom MyPad object inheriting from TPad. MyPad::ExecuteEvent(){} is left empty which keeps the user from manually resizing the pad.[/li][/ol]