How to connect a callback function to its signal

283 Views Asked by At

i created two buttons a that display a Gtk_Radio_Button and a button that display a GtK_label but when i click on buttons nothing happens. I don't understand why it doesn't work yet the code compiles and runs without finding any error.

main_Program.adb

With Gtk.Window;     Use Gtk.Window;
With Gtk.Button;     Use Gtk.Button;
With Gtk.Grid;       Use Gtk.Grid;
With file;           Use file;

Procedure main_program is
   
   Bouton : Gtk_Button;
   Bouton2 : Gtk_Button;
   Win : Gtk_Window;
   Test : Test_Record;
   
begin
   Gtk.Main.Init;
   
   Init_Grid (Container => Test);
   
   Gtk_New (Win);
   
   Win.Add (Test.Grid);
   
   Win.Set_Default_Size (Width  => 600,
                         Height => 400);
   
   Gtk_New (Bouton,Label => "Bouton");
   Test.Grid.Attach (Bouton,0,0);
   
   P.Connect (Widget => Bouton,
              Name   => Signal_Clicked,
              Marsh  => Test2.P.To_Marshaller (Init_Button'Access),
              After  => False);
   
   Gtk_New (Bouton2,Label => "Bouton2");
   Test.Grid.Attach (Bouton2,50,4);
   
   P.Connect (Widget => Bouton2,
              Name   => Signal_Clicked,
              Marsh  => Test2.P.To_Marshaller (Init_Text'Access),
              After  => False);
   
   Win.Show_All;
   
   Main;   
end Main_Program;

file.ads

With Gtk.Label;          Use Gtk.Label;
With Gtk.Radio_Button;   Use Gtk.Radio_Button;
With Gtk.Grid;           Use Gtk.Grid;
With Gtk.Handlers;

Package file is
   
   type Test_Record is record
      
      Text : Gtk_Label;
      Grid : Gtk_Grid;
      Button_Radio : Gtk_Radio_Button;
      
   end record;
   
   Procedure Init_Text ( Self : access Gtk_Widget_Record'Class );

   --   Callback for create the text
   
   Procedure Init_Button (Self : access Gtk_Widget_Record'Class );

   --   Callback for Initialize the Radio Button;
   
   Procedure Init_Grid (Container : out Test_Record);

   --   Initialize the Gtk.Grid.Gtk_Grid
   
   Package P is new Gtk.Handlers.Callback (Gtk_Widget_Record);
   
   Use P;
   
end file;

file.adb

With file;        Use file;

Package body file is
   
   Procedure Init_Grid ( Container : out Test_Record ) is
   begin
      
      Gtk_New (Container.Grid);
      
   end Init_Grid;
   
   Procedure Init_Button ( Self : access Gtk_Widget_Record'Class ) is
      
      V : Test_Record;
   begin
      Init_Grid (Container => V);
      
      Gtk_New (V.Button_Radio,
               Group => null,
               Label => "Button Radio");
      
      V.Grid.Attach (V.Button_Radio,0,50);
      
      V.Grid.Show;
      
   end Init_Button;
   
   Procedure Init_Text (Self : access Gtk_Widget_Record'Class) is
      
      V : Test_Record;
   begin
      Init_Grid (Container => V);
      
      Gtk_New (V.Text);
      
      V.Text.Set_Label ("Hello,World");
      
      V.Grid.Attach (V.Text,150,0);
      
      V.Grid.Show;
      
   end Init_Text;
end file;

I want that when I click on the first button it shows me a radio button and when I click on the second button it shows me a label.

1

There are 1 best solutions below

0
On

I would consider to not create/destroy the label and radio button, but just toggle their visibility instead. Furthermore, I would also recommend to derive the main window from the GTK window type and always properly terminate the application when requested (see Destroy_Event_Callback in the example below).

app.ads

package App is

end App;

app-main_window.ads

with Gtk.Window;       use Gtk.Window;
with Gtk.Grid;         use Gtk.Grid;
with Gtk.Button;       use Gtk.Button;
with Gtk.Check_Button; use Gtk.Check_Button;
with Gtk.Label;        use Gtk.Label;  

package App.Main_Window is

   type App_Main_Window_Record is new Gtk_Window_Record with private;
   type App_Main_Window is access all App_Main_Window_Record'Class;

   ------------------
   -- Constructors --
   ------------------

   procedure Gtk_New
     (Main_Window : out App_Main_Window);
   procedure Initialize
     (Main_Window : not null access App_Main_Window_Record'Class);

private
   
   Window_Width  : constant := 300;
   Window_Height : constant := 100;     
   
   type App_Main_Window_Record is
     new Gtk.Window.Gtk_Window_Record with
      record
         Grid         : Gtk_Grid;        
         Button_1     : Gtk_Button;
         Button_2     : Gtk_Button;
         Check_Button : Gtk_Check_Button;
         Label        : Gtk_Label;
      end record;

end App.Main_Window;

app-main_window.adb

with Gtk.Main;
with Gtk.Widget;
with Gtk.Window;
with Gdk.Event;

package body App.Main_Window is

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

   function On_Button_1_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean;
   
   function On_Button_2_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean;

   -------------
   -- Gtk_New --
   -------------

   procedure Gtk_New (Main_Window : out App_Main_Window) is
   begin
      Main_Window := new App_Main_Window_Record;
      App.Main_Window.Initialize (Main_Window);
   end Gtk_New;

   ----------------
   -- Initialize --
   ----------------

   procedure Initialize
     (Main_Window : not null access App_Main_Window_Record'Class)
   is
   begin

      --  Initialize and setup the window.
      Gtk.Window.Initialize (Main_Window);
      
      Main_Window.Set_Title ("Demo Window");
      Main_Window.Set_Size_Request (Window_Width, Window_Height);
      Main_Window.Set_Resizable (False);

      --  Attach callback: properly end the GTK application when requested.
      Main_Window.On_Destroy
        (Call => Destroy_Event_Callback'Access);

      --  Add a grid.
      Gtk_New (Main_Window.Grid);
      Main_Window.Grid.Set_Hexpand (True);
      Main_Window.Grid.Set_Vexpand (True);
      Main_Window.Grid.Set_Column_Homogeneous (True);
      Main_Window.Grid.Set_Row_Homogeneous (True);
      
      Main_Window.Add (Main_Window.Grid);
      
      --  Create the two buttons.
      Gtk_New (Main_Window.Button_1, Label => "Button 1");
      Gtk_New (Main_Window.Button_2, Label => "Button 2");
      
      --  Insert both buttons into the grid.
      --
      --            +------+------+
      --            |      |      | 
      --            +------+------+
      --  (0,1) --> | XXXX | XXXX | <-- (1,1)
      --            +------+------+
      
      Main_Window.Grid.Attach
        (Child => Main_Window.Button_1,
         Left  => 0,
         Top   => 1);
      
      Main_Window.Grid.Attach
        (Child => Main_Window.Button_2,
         Left  => 1,
         Top   => 1);
      
      --  Attach "button pressed" callbacks.
      Main_Window.Button_1.On_Button_Press_Event
        (Call => On_Button_1_Pressed_Callback'Access);
      Main_Window.Button_2.On_Button_Press_Event
        (Call => On_Button_2_Pressed_Callback'Access);
      
      --  Create new label and check button.
      Gtk_New (Main_Window.Label, Str => "Hello World!");
      Gtk_New (Main_Window.Check_Button, Label => "A Check Button");      
      
      --  Insert both into the grid.
      --
      --            +------+------+
      --  (0,0) --> | XXXXXXXXXXX |   Width: 2 columns
      --            +------+------+
      --            |      |      |
      --            +------+------+
            
      Main_Window.Grid.Attach
        (Child => Main_Window.Label,
         Left  => 0,
         Top   => 0,
         Width => 2);
      
      Main_Window.Grid.Attach
        (Child => Main_Window.Check_Button,
         Left  => 0,
         Top   => 0,
         Width => 2);
      
      --  Show everything except the check button.
      Main_Window.Show;
      Main_Window.Grid.Show;
      Main_Window.Button_1.Show;
      Main_Window.Button_2.Show;
      Main_Window.Label.Show;

   end Initialize;

   ----------------------------
   -- 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;

   ----------------------------------
   -- On_Button_1_Pressed_Callback --
   ----------------------------------

   function On_Button_1_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean
   is
      --                (parent)      (parent)
      --  Button (Self) -------> Grid -------> Window
      
      Grid   : Gtk_Grid := Gtk_Grid (Self.Get_Parent);
      Window : App_Main_Window := App_Main_Window (Grid.Get_Parent);
      
   begin
      --  Just toggle visibility.
      Window.Label.Set_Visible (False);
      Window.Check_Button.Set_Visible (True);
      return True;   --  GDK_EVENT_STOP, do not propagate event to parent.

   end On_Button_1_Pressed_Callback;

   ----------------------------------
   -- On_Button_2_Pressed_Callback --
   ----------------------------------

   function On_Button_2_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean
   is
      Grid   : Gtk_Grid := Gtk_Grid (Self.Get_Parent);
      Window : App_Main_Window := App_Main_Window (Grid.Get_Parent);

   begin
      Window.Label.Set_Visible (True);
      Window.Check_Button.Set_Visible (False);
      return True;   --  GDK_EVENT_STOP, do not propagate event to parent.

   end On_Button_2_Pressed_Callback;   
   
end App.Main_Window;

main.adb

with Gtk.Main;
with App.Main_Window;

procedure Main is
   use App.Main_Window;
   Main_Window : App_Main_Window;
begin
   Gtk.Main.Init;
   Gtk_New (Main_Window);
   Gtk.Main.Main;
end Main;