【问题标题】:Getting Event Source Pointer from Ada Event Handler Parameters从 Ada 事件处理程序参数获取事件源指针
【发布时间】:2015-06-29 03:13:25
【问题描述】:

使用 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'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);

执行视图转换。

【问题讨论】:

  • 为了迂腐,视图转换(像任何类型转换一样)看起来像函数调用;可能不像一个那样实现。

标签: gtk ada


【解决方案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。

【讨论】:

  • 这对我来说很陌生。 Gtk.Widget.Gtk_Widget_Record 在哪里出现?传递给处理程序的是 Gtk.Widget.Gtk_Widget_Record'Class。这会自行编译,但我无法从连接调用中引用它(没有候选解释匹配)。我认为这是因为签名不匹配。
  • 抱歉,如果我误解了您的问题——我的代码是一个简化版本,(我希望)展示了一个可能的解决方案。我声明Widget_Record 对应于Gtk.Widget.Gtk_Widget_Record,因为我不需要(不需要)访问真实的东西。我的On_Click 的主体应该很容易转化为您的环境; Selected_Program_Button := Gtk_Radio_Button (Button);
  • 好的。这并不像我想象的那么复杂。我将根据您的帮助在我的问题中发布我的解决方案。谢谢。
猜你喜欢
  • 2020-07-28
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多