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:
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.
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.
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?
You may try with “size-allocate” signal and gtk_widget_set_size_request(). Compile this example and see how it works for you: OSK example ($697) · Snippets · GitLab
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
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.
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.