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

如何销毁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信号绑定该处理函数,最终导致回调逻辑完全未生效。

修复步骤

  1. 在Glade中绑定窗口的delete-event信号:给ID为window的窗口添加信号绑定,指定处理函数为on_window_delete_event
  2. 修正回调函数名与注册代码:确保回调函数名、注册的信号名称与Glade中的配置完全一致
  3. 正确处理关闭逻辑: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:32:01