You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GtkAda颜色获取失败求助:回调函数Self变量未正确初始化

问题:GtkAda中无法获取ColorButton选择的颜色

代码可编译运行,但无法获取用户选择的颜色,运行时触发GTK断言错误,输出的颜色值为未初始化的垃圾值。不确定如何在window_callbacks.adb的On_Color1_Color_Set过程中正确获取触发信号的ColorButton对象,对应的C代码运行正常,寻求解决方法。

运行输出

$ ./xml_code
Loading of XML is OK

(xml_code:31196): Gtk-CRITICAL **: 22:24:59.048: gtk_color_chooser_get_rgba: assertion 'GTK_IS_COLOR_CHOOSER (chooser)' failed
Red :  0.00000000000000E+00
Green :  6.64864036484338E-310
Blue :  6.95298171953014E-310
Alpha :  6.64864036156160E-310

(xml_code:31196): Gtk-CRITICAL **: 22:25:02.163: gtk_color_chooser_get_rgba: assertion 'GTK_IS_COLOR_CHOOSER (chooser)' failed
Red :  0.00000000000000E+00
Green :  6.64864036484338E-310
Blue :  6.95298171953014E-310
Alpha :  6.64864036156160E-310
^C
$

代码文件

xml_code.adb

--=- xml_code.adb -=-    
-- units from Gtk
with Gtk.Main;
with Glib.Error;     use Glib.Error;
with Gtk.Widget;     use Gtk.Widget;
with Gtk.Builder;    use Gtk.Builder;
with Gtkada.Builder; use Gtkada.Builder;

-- Ada predefined units
with Ada.Text_IO;    use Ada.Text_IO;
with Ada.Exceptions;

-- Application specific units
with Window_Callbacks; use Window_Callbacks;

procedure XML_Code is

  Builder         : Gtkada_Builder;
  Error           : aliased Glib.Error.GError;

  -- xml / Glade
  Mon_Interface   : Constant String := "<?xml version=""1.0"" encoding=""UTF-8""?>"
& "<!-- Generated with glade 3.40.0 -->"
& "<interface>"
& "  <requires lib=""gtk+"" version=""3.24""/>"
& "  <object class=""GtkAdjustment"" id=""adjustment1"">"
& "    <property name=""upper"">100</property>"
& "    <property name=""step-increment"">1</property>"
& "    <property name=""page-increment"">10</property>"
& " </object>"
& " <object class=""GtkListStore"" id=""liststore1"">"
& "    <columns>"
& "      <!-- column-name Col_1 -->"
& "      <column type=""gchararray""/>"
& "    </columns>"
& "    <data>"
& "      <row>"
& "        <col id=""0"">Ligne-1</col>"
& "      </row>"
& "      <row>"
& "        <col id=""0"">bbb</col>"
& "      </row>"
& "      <row>"
& "        <col id=""0"">dddd</col>"
& "      </row>"
& "      <row>"
& "        <col id=""0"">eeeeeeee</col>"
& "      </row>"
& "      <row>"
& "        <col id=""0"">ligne-5</col>"
& "      </row>"
& "      <row>"
& "        <col id=""0"">ligne-6</col>"
& "      </row>"
& "    </data>"
& "  </object>"
& "  <object class=""GtkWindow"" id=""window"">"
& "    <property name=""name"">window</property>"
& "    <property name=""width-request"">89</property>"
& "    <property name=""height-request"">3</property>"
& "    <property name=""can-focus"">False</property>"
& "    <property name=""hexpand"">True</property>"
& "    <property name=""vexpand"">True</property>"
& "    <property name=""border-width"">0</property>"
& "    <property name=""window-position"">center</property>"
& "    <property name=""gravity"">center</property>"
& "    <child>"
& "      <object class=""GtkFixed"" id=""fixed1"">"
& "        <property name=""name"">fixed1</property>"
& "        <property name=""visible"">True</property>"
& "        <property name=""can-focus"">False</property>"
& "        <child>"
& "          <object class=""GtkColorButton"" id=""color1"">"
& "            <property name=""width-request"">100</property>"
& "            <property name=""height-request"">33</property>"
& "            <property name=""visible"">True</property>"
& "            <property name=""can-focus"">True</property>"
& "            <property name=""receives-default"">True</property>"
& "            <signal name=""color-set"" handler=""on_color1_color_set"" swapped=""no""/>"
& "          </object>"
& "          <packing>"
& "            <property name=""x"">298</property>"
& "            <property name=""y"">303</property>"
& "          </packing>"
& "        </child>"
& "      </object>"
& "    </child>"
& "  </object>"
& "</interface>";

  use type Glib.Guint;
     
  begin

    Gtk.Main.Init;

    Gtk_New (Builder);
    if Add_From_String (Gtk_Builder(Builder), Mon_Interface, Error'Access) = 0 then
      Put_Line ("Error : " & Get_Message (Error));
      Error_Free (Error);
      return;
    end if;
    Put_Line ("Loading of XML is OK ");

    Register_Handler (Builder, "on_window1_delete_event", On_Window1_Delete_Event'Access);

    Register_Handler (Builder, "on_color1_color_set",     On_Color1_Color_Set'Access);

    Do_Connect (Builder);

    Show_All (Gtk_Widget (Get_Object (GTK_Builder (Builder), "window")));

    Gtk.Main.Main;

    Unref (Builder);

  end XML_Code;

window_callbacks.ads

--=- window_callbacks.ads -=- 
with Gtkada.Builder; use Gtkada.Builder;

package Window_Callbacks is

  function On_Window1_Delete_Event (Builder : access Gtkada_Builder_Record'Class) return Boolean;  --Ajout
  Procedure On_Color1_Color_Set    (Builder : access Gtkada_Builder_Record'Class);

end Window_Callbacks;

window_callbacks.adb

--=- window_callbacks.adb --=--    
-- units from GtkAda
with Gtk.Main;

with Gtk.Color_Chooser;           use Gtk.Color_Chooser;
with Gdk.RGBA;                    use Gdk.RGBA;

-- units from Glib
with Glib;              use Glib;

-- Ada predefined units
with Ada.Text_IO;       use Ada.Text_IO;


package body Window_Callbacks  is

  -----------------------------------------------
  -- On_Window1_Delete_Event
  -----------------------------------------------
  function On_Window1_Delete_Event 
                 (Builder : access Gtkada_Builder_Record'Class) return Boolean is
    pragma Unreferenced (Builder); -- C'est sciemment que Builder n'est pas utilisé dans la fonction
    begin
      Gtk.Main.Main_Quit;
      return False;
    end On_Window1_Delete_Event;

  ---------------------------------
  -- On_Color1_Color_Set  --
  ---------------------------------
  procedure On_Color1_Color_Set (Builder : access Gtkada_Builder_Record'Class) is
    pragma Unreferenced (Builder);

    Self  : Gtk_Color_Chooser;
    Color : Gdk_RGBA;
    begin
    
      Gtk.Color_Chooser.Get_RGBA (Self, Color);
    
      put_line ("Red : "   &  Gdouble'Image (Color.Red));
      put_line ("Green : " &  Gdouble'Image (Color.Green));     
      put_line ("Blue : "  &  Gdouble'Image (Color.Blue));    
      put_line ("Alpha : " &  Gdouble'Image (Color.Alpha));
    
    end On_Color1_Color_Set;

end Window_Callbacks;

解决方案

问题核心是On_Color1_Color_Set过程中未正确获取触发信号的GtkColorButton对象,当前代码中的Self变量未初始化,导致调用Get_RGBA时触发断言错误。

修改步骤:

  1. 调整回调函数参数类型
    在window_callbacks.ads中,将On_Color1_Color_Set的参数从Builder改为Widget,因为信号发送者是ColorButton控件而非Builder:

    --=- window_callbacks.ads -=- 
    with Gtk.Widget; use Gtk.Widget;
    
    package Window_Callbacks is
    
      function On_Window1_Delete_Event (Builder : access Gtkada.Builder.Gtkada_Builder_Record'Class) return Boolean;
      Procedure On_Color1_Color_Set    (Widget : access Gtk_Widget_Record'Class);
    
    end Window_Callbacks;
    
  2. 更新回调函数实现
    在window_callbacks.adb中,将参数转换为Gtk_Color_Chooser类型(GtkColorButton实现了该接口),再调用Get_RGBA获取颜色:

    --=- window_callbacks.adb --=--    
    -- units from GtkAda
    with Gtk.Main;
    with Gtk.Widget; use Gtk.Widget;
    with Gtk.Color_Chooser;           use Gtk.Color_Chooser;
    with Gdk.RGBA;                    use Gdk.RGBA;
    
    -- units from Glib
    with Glib;              use Glib;
    
    -- Ada predefined units
    with Ada.Text_IO;       use Ada.Text_IO;
    
    
    package body Window_Callbacks  is
    
      -----------------------------------------------
      -- On_Window1_Delete_Event
      -----------------------------------------------
      function On_Window1_Delete_Event 
                     (Builder : access Gtkada.Builder.Gtkada_Builder_Record'Class) return Boolean is
        pragma Unreferenced (Builder);
        begin
          Gtk.Main.Main_Quit;
          return False;
        end On_Window1_Delete_Event;
    
      ---------------------------------
      -- On_Color1_Color_Set  --
      ---------------------------------
      procedure On_Color1_Color_Set (Widget : access Gtk_Widget_Record'Class) is
        Color_Chooser : Gtk_Color_Chooser := Gtk_Color_Chooser (Widget);
        Color : Gdk_RGBA;
        begin
          Get_RGBA (Color_Chooser, Color);
          
          Put_Line ("Red : "   & Gdouble'Image (Color.Red));
          Put_Line ("Green : " & Gdouble'Image (Color.Green));     
          Put_Line ("Blue : "  & Gdouble'Image (Color.Blue));    
          Put_Line ("Alpha : " & Gdouble'Image (Color.Alpha));
        end On_Color1_Color_Set;
    
    end Window_Callbacks;
    
  3. 信号注册无需修改
    xml_code.adb中的信号注册逻辑保持不变,因为XML中swapped="no",GtkAda会自动将信号发送者传递给回调函数。

修改说明

  • GTK信号回调的默认第一个参数是发送信号的控件对象,而非Builder,之前的参数定义错误导致无法获取目标控件。
  • GtkColorButton是GtkColorChooser接口的实现类,可安全将Gtk_Widget转换为Gtk_Color_Chooser类型。

修改后运行代码,即可正确获取用户选择的颜色值,不再出现断言错误和垃圾值。

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 07:59:52