GtkAda颜色获取失败求助:回调函数Self变量未正确初始化
代码可编译运行,但无法获取用户选择的颜色,运行时触发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时触发断言错误。
修改步骤:
调整回调函数参数类型
在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;更新回调函数实现
在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;信号注册无需修改
xml_code.adb中的信号注册逻辑保持不变,因为XML中swapped="no",GtkAda会自动将信号发送者传递给回调函数。
修改说明
- GTK信号回调的默认第一个参数是发送信号的控件对象,而非Builder,之前的参数定义错误导致无法获取目标控件。
GtkColorButton是GtkColorChooser接口的实现类,可安全将Gtk_Widget转换为Gtk_Color_Chooser类型。
修改后运行代码,即可正确获取用户选择的颜色值,不再出现断言错误和垃圾值。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

