从Ada事件处理程序参数获取事件源指针

时间:2015-06-29 03:13:26

标签: gtk ada

使用GtkAda,我想确定哪个单选按钮被切换。

我提出的最好的是这个不是很漂亮的代码,它迭代所有按钮以找到切换的那些:

   procedure On_Pgm_Btn_Click
      (Button : access Gtk.Widget.Gtk_Widget_Record'Class) is

     Button_Array : array (Positive range <>) of Gtk_Radio_Button := (Pgm_Bit, Pgm_1, Pgm_2, Pgm_3, Pgm_4);

   begin
     for Index In Button_Array'range loop
        if Button_Array(Index).Get_Active then
           Selected_Program_Button := Button_Array(Index);
           exit; 
        end if;
     end loop;
  end On_Pgm_Btn_Click;   

使用此处理程序连接代码调用此方法:

   Gtkada.Handlers.Widget_Callback.Connect (Pgm_Bit, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_1, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_2, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_3, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_4, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   

我可以在调试器中看到参数 Button 的值与生成事件的按钮具有相同的地址,但我不知道此参数的常规方式是用过的。它的类型是Gtk.Widget.Gtk_Widget_Record&#39; Class,它告诉我,如果我对一个单选按钮进行了未经检查的转换,我可能会破解代码;

如何从参数按钮中获取单选按钮?

(另外,如果有更好的方式来获得单选按钮组的状态,我想知道。我还没有找到任何好的例子。)

更新解决方案
从下面接受的答案中,我了解到视图转换的实现就像函数调用一样,如ARM 4.6的示例所示。处理程序变成了这个:

procedure On_Pgm_Btn_Click
  (Button : access Gtk.Widget.Gtk_Widget_Record'Class) is

  This_Button : Gtk_Radio_Button;

begin
  This_Button := Gtk_Radio_Button(Button);
  if This_Button.Get_Active then
     Selected_Program_Button := This_Button;
  end if;
end On_Pgm_Btn_Click;

所涉及的类型已在gtk-radio-button.ads中定义为:

   type Gtk_Radio_Button_Record is new Gtk_Check_Button_Record with null record;
   type Gtk_Radio_Button is access all Gtk_Radio_Button_Record'Class;

并在gtk_widget.ads中:

   type Gtk_Widget_Record is new GObject_Record with null record;
   type Gtk_Widget is access all Gtk_Widget_Record'Class;

因此没有理由重新定义它们或使用接受的答案中提供的包和示例代码。

修改后的代码中的重要一行是:

This_Button := Gtk_Radio_Button(Button);

执行视图转换。

1 个答案:

答案 0 :(得分:1)

这应该由视图转换(ARM 4.6(5))处理,而不是未经检查的转化。

我没有安装Gtk,所以我写了这篇文章(经过AdaCore’s documentation的一些研究后),我相信它是一个自包含的等价物,并且用GCC 5.1.0成功编译。

package View_Conversions is

   type Widget_Record is tagged null record;
   --  Represents Gtk.Widget.Gtk_Widget_Record

   type Button_Record is new Widget_Record with null record;
   type Button is access all Button_Record'Class;
   --  Represents Gtk.Radio_Button.Gtk_Radio_Button

   procedure On_Click (Widget : access Widget_Record'Class);

end View_Conversions;

身体

package body View_Conversions is

   Selected : Button;
   --  Records the selected button

   procedure On_Click (Widget : access Widget_Record'Class) is
   begin

      Selected := Button (Widget);
      --  If the Widget is a Button, save it; if not, raise CE

   end On_Click;

end View_Conversions;

优于未选中转化的优势在于,这是经过检查的转化,如果传递的Widget实际上不是Button,那么您将获得Constraint_Error转换。