how i can to align a widget with Gtk_Grid

632 Views Asked by At

i've this code

Main.adb

With Gtk.Main;         Use Gtk.Main;
With Gtk.Window;       Use Gtk.Window;
With Gtk.Button;       Use Gtk.Button;
With Gtk.Widget;       Use Gtk.Widget;
With Gtk.Grid;         Use Gtk.Grid;

Procedure Main is

   Win : Gtk_Window;
   Button : Gtk_Button;
   Button2 : Gtk_Button;
   Button3 : Gtk_Button;
   Grid : Gtk_Grid;

begin
   Init;

   Gtk_New (Win);
   Win.Set_Default_Size (Width  => 380,
                         Height => 502);

   Gtk_New (Button,"Button");

   Gtk_New (Button2,"Button2");
   
   Gtk_New (Button3,"Button3");

   Gtk_New (Grid);

   Grid.Attach (Button,0,0);

   Grid.Attach (Button2,0,100);
   
   Grid.Attach (Button3,75,20);
   
   Win.Add (Grid);

   Win.Show_All;
   Gtk.Main.Main;
end Main;

here I would like my first button to be at the top on the far left, my third button to the right but at the bottom and my Second button must be at the bottom. I tried almost all the methods but still in vain I can't align my widgets correctly so does anyone have an idea on how I can align all my widgets with a Gtk_Grid.

2

There are 2 best solutions below

2
On

You can just add widgets to cells. As is already stated in the comment, the Top and Left parameters of Attach represent the cell indices (row/column), not pixels. See the annotated example below.

If you want to position a widget using coordinates, then you can use a GTK Fixed container. Be aware, however, that this container is almost never a good solution for positioning widgets; widgets should, in principle, always be positioned using layout containers HBox, VBox, Table, Grid and Layout. This is to ensure proper widget composition regardless of the screen resolution and screen size of the user. This is emphasized in the description of the Fixed widget:

For most applications, you should not use this container! It keeps you from having to learn about the other GTK+ containers, but it results in broken applications.

I've added an example that shows the usage of both container widgets, Grid and Fixed. In these example, I've moved the GTK code into a separate package in order to add a Destroy_Event_Callback which in turn will call Gtk.Main.Main_Quit to stop the GTK event loop and properly exit the program when you close the window.

app.adb (using GTK Fixed, see manual and GtkAda source)

with Gtk.Main;   use Gtk.Main;
with Gtk.Window; use Gtk.Window;
with Gtk.Button; use Gtk.Button;
with Gtk.Widget; use Gtk.Widget;
with Gtk.Fixed;  use Gtk.Fixed;

package body App is

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class);

   ---------
   -- Run --
   ---------

   procedure Run is

      Win      : Gtk_Window;
      Button_1 : Gtk_Button;
      Button_2 : Gtk_Button;
      Button_3 : Gtk_Button;
      Fixed    : Gtk_Fixed;

   begin
      Gtk.Main.Init;

      Gtk_New (Win);
      Win.Set_Default_Size (Width => 380, Height => 502);
      Win.On_Destroy (Call => Destroy_Event_Callback'Access);

      Gtk_New (Button_1, "Button 1");
      Gtk_New (Button_2, "Button 2");
      Gtk_New (Button_3, "Button 3");

      Gtk_New (Fixed);

      --  Add the buttons to the container with their
      --  top-left corner at the specified coordinate.
      Fixed.Put (Button_1, X =>   0, Y =>   0);
      Fixed.Put (Button_2, X =>  50, Y => 100);   
      Fixed.Put (Button_3, X => 200, Y => 100);      

      Win.Add (Fixed);
      Win.Show_All;

      Gtk.Main.Main;

   end Run;

   ----------------------------
   -- Destroy_Event_Callback --
   ----------------------------

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class)
   is
   begin
      Gtk.Main.Main_Quit;
   end Destroy_Event_Callback;

end App;

app.adb (using GTK Grid, see manual and GtkAda source)

with Gtk.Main;   use Gtk.Main;
with Gtk.Window; use Gtk.Window;
with Gtk.Button; use Gtk.Button;
with Gtk.Widget; use Gtk.Widget;
with Gtk.Grid;   use Gtk.Grid;

package body App is

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class);
   
   ---------
   -- Run --
   ---------

   procedure Run is
   
      Win      : Gtk_Window;
      Button_1 : Gtk_Button;
      Button_2 : Gtk_Button;
      Button_3 : Gtk_Button;
      Grid     : Gtk_Grid;

   begin
      Gtk.Main.Init;

      Gtk_New (Win);
      Win.Set_Default_Size (Width => 380, Height => 502);
      Win.On_Destroy (Call => Destroy_Event_Callback'Access);
   
      Gtk_New (Button_1, "Button 1");
      Gtk_New (Button_2, "Button 2");
      Gtk_New (Button_3, "Button 3");

      Gtk_New (Grid);
   
      --  Stretch the grid to the size of the window.
      Grid.Set_Hexpand (True);      
      Grid.Set_Vexpand (True);
   
      --  Make all cells have the same width/height.
      Grid.Set_Column_Homogeneous (True);
      Grid.Set_Row_Homogeneous (True);

      --  Insert the buttons into the grid.
      --    
      --      Left:    0      1      2
      --   Top:    +------+------+------+
      --        0  | Btn1 |      |      |
      --           +------+------+------+
      --        1  |      | Btn3 | Btn2 |
      --           +------+------+------+
      --
      Grid.Attach (Button_1, Left => 0, Top => 0);
      Grid.Attach (Button_2, Left => 2, Top => 1);
      Grid.Attach (Button_3, Left => 1, Top => 1);   
   
      Win.Add (Grid);
      Win.Show_All;
   
      Gtk.Main.Main;
   
   end Run;   
   
   ----------------------------
   -- Destroy_Event_Callback --
   ----------------------------

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class)
   is
   begin
      Gtk.Main.Main_Quit;
   end Destroy_Event_Callback;

end App;

app.ads

package App is

   procedure Run;

end App;

main.adb

with App;

procedure Main is
begin
   App.Run;
end Main;
1
On

hello here I tried to find a solution so I created a gtk_alignment then I added it to my gtk_grid but a concern in all that is that gtk_alignment does not align the widget at the defined place

here the new code

Main.adb

With Gtk.Main;         Use Gtk.Main;
With Gtk.Window;       Use Gtk.Window;
With Gtk.Button;       Use Gtk.Button;
With Gtk.Widget;       Use Gtk.Widget;
With Gtk.Grid;         Use Gtk.Grid;
With Test2;            Use Test2;
With Gtk.Alignment;    Use Gtk.Alignment;

Procedure Main is

   Win : Gtk_Window;
   Button_1 : Gtk_Button;
   Button_2 : Gtk_Button;
   Grid : Gtk_Grid;
   Align : Gtk_Alignment;

begin
   Init;

   Gtk_New (Win);
   Win.Set_Default_Size (Width  => 300, Height => 502);

   Win.On_Destroy (Test2.Exit_Window'Access);

   Gtk_New (Grid);

   --   Initialize the Gtk.Button.Gtk_Button
   
   Gtk_New (Button_1,"Button 1");
   
   Gtk_New (Button_2,"Button 2");

   --   Add the Button_1
   
   Grid.Attach (Button_1,0,0);
   
   -- Initialize Gtk_Alignment and align the button_2
   
   Gtk_New (Align,
            Xalign => 0.5,
            Yalign => 1.0,
            Xscale => 1.0,
            Yscale => 0.2);
   
   Align.Add (Button_2);
   Grid.Add (Align);
   
   Win. Add (Grid);

   Win.Show_All;

   Gtk.Main.Main;
end Main;

I want my first button to be at the very top left of the window and my second button at the bottom of the window.