Is it possible to set widget size proportions with GTK (e.g. inside GtkBox)?

Hi! I’m new to GTK and trying to make a simple music synthesizer app with it. One of the UI elements is a screen keyboard to indicate pressed buttons:


I implemented it using vertical GtkBox containing 5 horizontal GtkBox's. I want all the keys to be the same size and for that, I set all GtkBox's homogeneous. But the number of keys in each row isn’t the same, so some rows should have dynamic margins on the left and right (as on screenshot). For now I just hardcoded them, but ideally, I want them to resize proportionally to other keys. How would it be possible to implement that?

I see multiple hypothetical solutions:

  1. I could put the keyboard into GtkGrid and just start last 2 rows not from the first collumn. For now it’s easy, I can have 24 collumns, each key is 2 cells horizontally, the last two rows starts at 1st and 2nd column accordingly. But if I’d want to change a layout just a bit (let’s say add escape key to the first row) the whole GtkGrid structure would need to be rethought.

  2. If it’s possible to set a callback for window resize event and get the new window size there, I could recalculate the margins in the callback. I didn’t find any appropriate event on GtkWindow and GtkWidget, is there one? Anyway, this solution looks uglier to me, and I’m not sure if the resize will remain smooth.

  3. Ideally, I would want some mechanism that allows setting proportions between GtkBox children sizes. I would put empty labels instead of margins. It would also allow to add keys with different sizes (e.g. “Shift” with 2.5x width compared to other buttons). Is it possible?

I’m using Rust and GTK-rs if it matters. Thanks for your time!

P.S. Is it the right place to ask questions like this? If no, I’m sorry, could you please point me where to go with it?

1 Like

Hi, you may try setting all 5 horizontal boxes as hexpand=false and halign=GTK_ALIGN_CENTER.

This way you get the layout in the picture but without having to manually set margins.

Hey, thanks a lot for your quick response! If I disable hexpand on horizontal boxes, the keys shrink to their minimum size:

I want the whole keyboard to expand as wide as possible.

Ah I see. Yes, then you should only set halign=GTK_ALIGN_CENTER. How does it work?
EDIT: nope that won’t work.

Maybe that’ a good candidate

Wow! It looks very flexible. The problem is that I’m writing it in Rust language and it looks like there are no bindings for it

You may try with “size-allocate” signal and gtk_widget_set_size_request(). Compile this example and see how it works for you:

EDIT: This also adds background to the labels:

1 Like

Would a GtkSizeGroup be simpler?

1 Like

Thank you very much for so much time spent on my problem! It works very smooth. I’ll stick with it for now.

Oh, wow! It looks even better. Will try, thank you!

Hi Peter! I proptotyped it in glade but did not work. Of course I may have missed something so feel free to try with this!

Looks like GtkSizeGroup uniforms the widgets minimum size, but after that a container may set a larger size and that is out of the scope of the GtkSizeGroup.

P.S: This is just my observation and I may be completely wrong :slight_smile:

Yeah, I have the same impression

This is a pretty bad idea. Calling set_size_request() inside a size-allocate callback will cause a layout cycle—the child will queue a resize right in the middle of being given a size, which will then cause a new frame to be requested.

If you want to implement a custom layout that mimics a physical keyboard you will either need to write your own layout manager, or you will need to use a container that doesn’t care about layout at all, like GtkFixed.

Yes, I agree it’s pretty risky…

Hm, understand, thanks. Then i’ll probably stick with hardcoded margins for now. It is simple and good enough looking. GtkFixed isn’t good solution for me because i want this screen keyboard to be resizable, and writing custom layout manager sounds too complicated (although i don’t really know what it implies).

Is there any technical or ideological reason why GtkBox doesn’t have control over children size proportions? It seems simple and very useful for many cases.

You’re both right! GtkSizeGroup sets the minimum and natural sizes, but it doesn’t know about additional space allocated by the container.

The GtkGrid approach looks like the cleanest solution. Looks like the leftmost column for the leftmost key in a row is (max row length - this row length), so changing the keyboard layout shouldn’t too big a hassle.

1 Like

Oh, I even forgot about GtkGrid solution after this discussion :smiley:
Thanks. Yeah, just reimplemented it with GtkGrid. Looks clean and simple

In Gtk±2.0 you would derive following class functions:

  • GtkWidget::realize()
  • GtkWidget::size-request()
  • GtkWidget::size-allocate()

I just checked the API reference manual, they are mentioned in Gtk3, too.

by Joël

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.