如何从 GtkAda 小部件中销毁按钮?

问题描述 投票:0回答:1

“当您关闭对话框时,X 按钮还需要缺少回调处理程序,否则它永远不会关闭并保留在后台。”我尝试了附加的代码来解决这个问题,但没有成功。代码执行不会停止.. -事实上,可能有 2 个类似的问题,它们是 a) X 按钮的寿命和关闭它的需要 b) 窗口的寿命和必要时关闭它。 -我的建议仅适用于窗户。我不知道如何正确解决a)。 谢谢 Ps :上一个线程后面的线程 @ 如何从 GtkAda 小部件中检索文件名?

    -- 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;
  procedure On_File1_File_Set (Builder : access Gtkada_Builder_Record'Class);
end Window_Callbacks;



-- window_callbacks.adb

-- units from GtkAda
with Gtk.Main;

-- units from GtkAda
with Gtk.File_Chooser;           use Gtk.File_Chooser;
with Gtk.File_Chooser_Button;    use Gtk.File_Chooser_Button;

with Gtkada.File_Selection;      use Gtkada.File_Selection;


-- units from Glib
with Glib;              use Glib;
with Glib.Object;       use Glib.Object;

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

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);
    begin
      Gtk.Main.Main_Quit;
      return False;
    end On_Window1_Delete_Event;

  ---------------------------------
  -- On_File1_File_Set  --
  ---------------------------------
  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
      -- Get the file chooser button
      Button := Gtk_File_Chooser_Button (Get_Object(Builder, "file1"));

      -- Get the filename
      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

-- 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;

-- Application specific units
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>"
  & "    <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;

    -- Etape 1 : créer un Builder
    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;
   
    -- Etape 2 : créer les handlers des events
    Register_Handler (Builder, "on_window1_delete_event", On_Window1_Delete_Event'Access);
    Register_Handler (Builder, "on_file1_file_set", On_File1_File_Set'Access);

    -- Etape 3 : Do_Connect connecte tous les handlers enregistrés en une fois.
    Do_Connect (Builder);

    -- Etape 4 : Afficher la fenetre avec ses dépendances
    Show_All (Gtk_Widget (Get_Object (GTK_Builder (Builder), "window")));

    -- Etape 5 : Lancer la boucle infinie.
    Gtk.Main.Main;

    -- Etape 6 : Unref pour libérer la memoire associée au Builder.
    Unref (Builder);

  end Glade_8;
widget ada destroy gtkada
1个回答
0
投票

X 按钮的工作原理是

User presses X
      |
      | Delete event
      v
Delete Event Callback must return False.  If True
is returned, the window will not be destroyed.  Do
not kill the loop here.  There are some tidyups that
need to happen after False is returned.  Let the
window manager handle the destroy event
      |
      | Destroy event
      v
Destroy Event Callback terminates the main loop.

我不知道如何使用构建器完成此操作,所以我只是告诉您我通常的做法。

如果您要执行多个程序,将回调放入一个包中并只需将该包从一个系统复制到另一个系统会更容易。

注意:有 2 个处理程序 - 一个用于过程,一个用于函数

-- xbuttonpkg.ads
with Gtk.Window; use Gtk.Window;
package XButtonPkg is
    procedure XButtonHandler (window: Gtk_Window);
end XButtonPkg;

-- xbuttonpkg.adb
with Gdk.Event;    use Gdk.Event;
with Gtk.Widget;   use Gtk.Widget;
with Gtk.Handlers; use Gtk.Handlers;
with Ada.Text_IO;  use Ada.Text_IO;
with Gtk.Main;  -- for quit

package body XButtonPkg is

   -- For callback procedures.
   package Handlers is new Gtk.Handlers.Callback(
      Widget_Type => Gtk_Widget_Record
   );

   -- For callback functions
   package Return_Handlers is new Gtk.Handlers.Return_Callback(
      Widget_Type => Gtk_Widget_Record,
      Return_Type => Boolean);

   -- The delete event callback is a function
   function Delete_Event(
      Widget : access Gtk_Widget_Record'Class;
      Event  : Gdk_Event)
      return Boolean
   is
      pragma Unreferenced (Event);
      pragma Unreferenced (Widget);
   begin
      --  If you return False in the "delete_event" signal handler,
      --  GtkAda will emit the "destroy" signal. Returning True means
      --  you don't want the window to be destroyed.

      Put_Line ("delete event occurred");

      --  False = issue a destroy event

      return False;
   end Delete_Event;

   -- The destroy callback event is a procedure
   procedure Destroy (Widget : access Gtk_Widget_Record'Class) is
      pragma Unreferenced (Widget);
   begin
      Put_Line ("quitting");
      Gtk.Main.Main_Quit;
   end Destroy;

   procedure XButtonHandler(window:Gtk_Window) is
   begin
      --  Handle X button
      --  When the window is given the "delete_event" signal (this is given
      --  by the window manager, usually by the "close" option, or on the
      --  titlebar), the Delete_Event function gets invoked
      Return_Handlers.Connect (
         window,
         "delete_event",
         Return_Handlers.To_Marshaller (Delete_Event'Access));

      --  Connect the "destroy" event to a signal handler.
      --  This event occurs when Gtk.Widget.Destroy is called on the window,
      --  or if False is returned by the "delete_event" calback.
      Handlers.Connect (
         window,
         "destroy",
         Handlers.To_Marshaller (Destroy'Access));
   end XButtonInit;
end XButtonPkg;

在主代码中,声明一个窗口对象

window: Gtk_Window;

删除删除事件 - 这是由 XButtonHandler 处理的。

更换

-- Etape 4 : Afficher la fenetre avec ses dépendances
Show_All (Gtk_Widget (Get_Object (GTK_Builder (Builder), "window")));

window := Gtk_Window (Get_Object (GTK_Builder (Builder), "window"));
XButtonHandler (window);
Show_All (window);

这应该可以工作 - 您将看到删除事件的一些输出,并再次看到销毁事件的输出,然后您的程序应该正确终止。

我没有经常使用构建器。 我会实验一下,看看是否有使用 builder 的方法。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.