如何销毁GtkAda组件按钮?窗口X按钮关闭回调失效求助
GtkAda 组件销毁与窗口关闭问题解决方案
一、销毁GtkAda中的按钮组件
要销毁GtkAda中的按钮(或任意Widget),核心是调用Destroy方法,同时遵循GTK的引用计数机制:
- 获取目标按钮对象(可通过Builder的
Get_Object根据ID获取) - 调用
Destroy(Button)方法,这会将按钮从父容器中移除并触发资源释放 - 若需彻底清理,可调用
Unref减少对象引用计数(当计数归0时,对象会被完全释放)
示例代码片段:
declare Button : access Gtk_Button_Record'Class; begin Button := Gtk_Button(Get_Object(Builder, "button_id")); Destroy(Button); end;
二、窗口X按钮关闭回调失效问题修复
你的代码中存在信号名称与绑定不匹配的核心问题,导致点击X按钮后回调未触发,程序无法正常终止:
问题根源
Glade定义的窗口ID为window,但你注册的回调名称是on_window1_delete_event,且未在Glade中为窗口的delete-event信号绑定该处理函数,最终导致回调逻辑完全未生效。
修复步骤
- 在Glade中绑定窗口的
delete-event信号:给ID为window的窗口添加信号绑定,指定处理函数为on_window_delete_event - 修正回调函数名与注册代码:确保回调函数名、注册的信号名称与Glade中的配置完全一致
- 正确处理关闭逻辑:
delete-event回调返回False表示允许GTK销毁窗口,同时调用Main_Quit终止主循环,确保程序彻底退出
修改后的关键代码
1. Glade界面定义(窗口部分)
在<object class="GtkWindow" id="window">节点内添加信号绑定:
<signal name="delete-event" handler="on_window_delete_event" swapped="no"/>
2. Window_Callbacks.ads(修正函数名)
with Gtkada.Builder; use Gtkada.Builder; package Window_Callbacks is function On_Window_Delete_Event (Builder : access Gtkada_Builder_Record'Class) return Boolean; procedure On_File1_File_Set (Builder : access Gtkada_Builder_Record'Class); end Window_Callbacks;
3. Glade_8主程序(修正回调注册)
Register_Handler (Builder, "on_window_delete_event", On_Window_Delete_Event'Access);
窗口与X按钮的生命周期逻辑
- X按钮触发流程:点击X按钮 → GTK发送
delete-event信号 → 回调函数执行 → 返回False允许窗口销毁 → 调用Main_Quit终止主循环,程序退出 - 窗口生命周期:窗口通过
Show_All显示,Destroy调用后从屏幕移除并释放资源;若未终止主循环,程序会驻留后台 - 必须绑定
delete-event回调并主动终止主循环,才能避免窗口关闭后程序残留
三、完整修正后的代码
window_callbacks.ads
with Gtkada.Builder; use Gtkada.Builder; package Window_Callbacks is function On_Window_Delete_Event (Builder : access Gtkada_Builder_Record'Class) return Boolean; procedure On_File1_File_Set (Builder : access Gtkada_Builder_Record'Class); end Window_Callbacks;
window_callbacks.adb
-- units from GtkAda with Gtk.Main; with Gtk.File_Chooser; use Gtk.File_Chooser; with Gtk.File_Chooser_Button; use Gtk.File_Chooser_Button; with Glib; use Glib; with Glib.Object; use Glib.Object; with Ada.Text_IO; use Ada.Text_IO; with Ada.Characters.Latin_1; use Ada.Characters.Latin_1; package body Window_Callbacks is function On_Window_Delete_Event (Builder : access Gtkada_Builder_Record'Class) return Boolean is pragma Unreferenced (Builder); begin Gtk.Main.Main_Quit; return False; end On_Window_Delete_Event; procedure On_File1_File_Set (Builder : access Gtkada_Builder_Record'Class) is Button : access Gtk_File_Chooser_Button_Record; function Name_Strict (File_Name : string) return string is I : natural := File_Name'Last; begin loop exit when File_Name (I) = Solidus or File_Name (I) = Reverse_Solidus or I = File_Name'First; I := @ - 1; end loop; if File_Name (I) = Solidus or File_Name (I) = Reverse_Solidus then return File_Name (I+1..File_Name'Last); --folder is present else return File_Name; -- folder is absent end if; end; begin Button := Gtk_File_Chooser_Button (Get_Object(Builder, "file1")); declare File_Name : constant string := Get_FileName (Button); Folder_Name : constant string := Get_Current_Folder (Button); begin Ada.Text_IO.Put_Line ("File selected : " & File_Name); Ada.Text_IO.Put_Line ("Current Folder : " & Folder_Name); Ada.Text_IO.Put_Line ("Strict File Name : " & Name_Strict (File_Name)); New_line; end; end On_File1_File_Set; end Window_Callbacks;
Glade_8主程序
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; with Ada.Text_IO; use Ada.Text_IO; with Window_Callbacks; use Window_Callbacks; procedure Glade_8 is Mon_Interface : Constant String := "<?xml version=""1.0"" encoding=""UTF-8""?>" & "<!-- Generated with glade 3.40.0 -->" & "<interface>" & " <requires lib=""gtk+"" version=""3.20""/>" & " <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 gchararray1 -->" & " <column type=""gchararray""/>" & " </columns>" & " <data>" & " <row>" & " <col id=""0"" translatable=""yes"">test1</col>" & " </row>" & " <row>" & " <col id=""0"" translatable=""yes"">test2</col>" & " </row>" & " <row>" & " <col id=""0"" translatable=""yes"">test3</col>" & " </row>" & " </data>" & " </object>" & " <object class=""GtkWindow"" id=""window"">" & " <property name=""can-focus"">False</property>" & " <signal name=""delete-event"" handler=""on_window_delete_event"" swapped=""no""/>" & " <child>" & " <object class=""GtkFixed"" id=""fixed1"">" & " <property name=""visible"">True</property>" & " <property name=""can-focus"">False</property>" & " <child>" & " <object class=""GtkFileChooserButton"" id=""file1"">" & " <property name=""width-request"">196</property>" & " <property name=""visible"">True</property>" & " <property name=""can-focus"">False</property>" & " <property name=""title"" translatable=""yes""/>" & " <signal name=""file-set"" handler=""on_file1_file_set"" swapped=""no""/>" & " </object>" & " <packing>" & " <property name=""x"">9</property>" & " <property name=""y"">234</property>" & " </packing>" & " </child>" & " </object>" & " </child>" & " </object>" & "</interface>"; Builder : Gtkada_Builder; Error : aliased Glib.Error.GError; 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; Register_Handler (Builder, "on_window_delete_event", On_Window_Delete_Event'Access); Register_Handler (Builder, "on_file1_file_set", On_File1_File_Set'Access); Do_Connect (Builder); Show_All (Gtk_Widget (Get_Object (GTK_Builder (Builder), "window"))); Gtk.Main.Main; Unref (Builder); end Glade_8;
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

