【问题标题】:How to create a file chooser with GtkAda?如何使用 GtkAda 创建文件选择器?
【发布时间】:2019-07-10 10:12:23
【问题描述】:

我正在尝试使用 GtkAda 创建一个应用程序,并且需要用户从他的 PC 中选择一个文件。但是,我发现无法创建文件选择器而不导致此错误:raised PROGRAM_ERROR : unhandled signal.

使用 Glade 3.22.1

我尝试创建一个文件选择器按钮并将其链接到文件选择器对话框。它会导致同样的错误。


没有林间空地

我尝试在 GPS 中创建文件选择器对话框和文件选择器按钮,但同样的错误。

然后我找到了 Gtkada.File_Selection 包。它的描述说它自己处理信号并且只需要一个功能。可悲的是,它导致了同样的致命错误。

我正在开发 Fedora 29。GtkAda 版本 2018、GPS 2018 和 GNAT 8.3.1。

Log_Filter_Handlers.ads

with Gtkada.File_Selection;   use Gtkada.File_Selection;

package Log_Filter_Handlers is

   Retour : Unbounded_String;


   procedure Button_Select_File_Clicked
     (Self : access Gtk_Button_Record'Class);

end Log_Filter_Handlers;

Log_Filter_Handlers.adb

   procedure Button_Select_File_Clicked
     (Self : access Gtk_Button_Record'Class) is

   begin

      Retour := To_Unbounded_String
        (File_Selection_Dialog (Title       => "Select your file",
                                Default_Dir => "",
                                Dir_Only    => False,
                                Must_Exist  => True) );

   end Button_Select_File_Clicked;

Gtkada-File_Selection.ads

package Gtkada.File_Selection is

function File_Selection_Dialog

      (Title       : Glib.UTF8_String := "Select File";
      Default_Dir : String := "";
      Dir_Only    : Boolean := False;
      Must_Exist  : Boolean := False) return String;

end Gtkada.File_Selection;

一旦应用程序创建了一个文件选择器小部件(无论是对话框还是按钮),在这种情况下通过调用 Button_Select_File_Clicked。它立即导致此错误: raised PROGRAM_ERROR : unhandled signal

我也有一些警告

Gtk-Message: 10:43:33.615: Failed to load module "pk-gtk-module"

Gtk-Message: 10:43:33.615: Failed to load module "canberra-gtk-module"

Gtk-Message: 10:43:33.616: Failed to load module "pk-gtk-module"

Gtk-Message: 10:43:33.616: Failed to load module "canberra-gtk-module"

Fontconfig warning: "/home/bob/Applications/Gnat_IDE/Gnat-community/etc/fonts/fonts.conf", line 86: unknown element "blank"

(log_filter_main:24417): Gtk-WARNING **: 10:43:33.841: Could not load a pixbuf from icon theme.

This may indicate that pixbuf loaders or the mime database could not be found.

谢谢。

【问题讨论】:

  • 听起来像是一个不完整的 GTK 安装(或两个相互不兼容的安装)你能检查一下你是否安装了 canberra 和 pk 并且你正在编译的版本是相同的吗?
  • PackageKit-gtk3-module-1.1.12-2.fc29.x86_64libcanberra-0.30-17.fc29.x86_64。堪培拉不再是问题,我通过更新 ldconfig 解决了它。但是,libpk 不断导致警告。我在 gtk-3.0/modules 文件夹中找不到 libpk-gtk3-module.so。这可能是警告的原因吗? ls /usr/lib64/gtk-3.0/moduleslibcanberra-gtk3-module.so libcanberra-gtk-module.so libpk-gtk-module.so

标签: gtk ada gtkada


【解决方案1】:

很难说是什么导致了未处理的信号错误。您可以考虑进行堆栈跟踪以查看引发异常的位置(另请参阅Rosetta code 上的示例)。

以下示例适用于 GNAT CE 2019。您可以在自己的环境中对其进行测试以查看问题是否仍然存在,或者使用在 GitHub 上找到的最新版本的 GtkAda 测试您自己的代码。


更新

快速搜索显示,从未从 GtkAda 引发带有消息“未处理信号”的 Program_Error。事实上,这种异常似乎只能发生在 GNAT/Ada 运行时(参见init.cseh_init.c)。而seh_init.c 仅用于针对 Win32 和 Cygwin 的运行时(请参阅该文件开头附近的 cmets),init.c 用于各种其他运行时,包括用于 Linux 的运行时。因此,我认为您观察到的 Program_Error 是在 init.c 中引发的,因为 GNAT/Ada 运行时无法处理某些 kernel 信号。

您可以通过跟踪发送到您的应用程序的信号来获得一些额外的信息(另请参阅 SO 上的this 帖子):

strace -e 'trace=!all' <program_name>

ma​​in.adb

with File_Selection_Demo;

procedure Main is
begin
   File_Selection_Demo.Run;
end Main;

file_selection_demo.ads

package File_Selection_Demo is

   procedure Run;

end File_Selection_Demo;

file_selection_demo.adb

with Ada.Text_IO;

with Gtk.Main;
with Gtk.Widget;
with Gtk.Builder;
with Gtk.Window;
with Gtk.Button;
with Gtk.GEntry;

with Gtkada.File_Selection;

with Glib;       use Glib;
with Glib.Error; use Glib.Error;

package body File_Selection_Demo is

   --  Widgets
   Builder : Gtk.Builder.Gtk_Builder;
   Window  : Gtk.Window.Gtk_Window;
   Button  : Gtk.Button.Gtk_Button;
   GEntry  : Gtk.GEntry.Gtk_Entry;


   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class);

   procedure Clicked_Event_Callback
     (Button : access Gtk.Button.Gtk_Button_Record'Class);


   ---------
   -- Run --
   ---------

   procedure Run is

      use Gtk.Builder;
      use Gtk.Window;
      use Gtk.Button;
      use Gtk.GEntry;

      Success : GUint;
      Error   : aliased GError;

   begin

      --  Initialize GtkAda.
      Gtk.Main.Init;

      -- Construct a Gtk_Builder instance and load our UI description.
      Gtk_New (Builder);

      Success := Builder.Add_From_File ("./example.glade", Error'Access);
      if Success = 0 then
         Ada.Text_IO.Put_Line ("failed to read Glade file");
         Error_Free (Error);         
         return;
      end if;

      --  Entry
      GEntry := Gtk_Entry (Builder.Get_Object ("Entry"));

      --  Button
      Button := Gtk_Button (Builder.Get_Object ("Button"));
      Button.On_Clicked (Clicked_Event_Callback'Access);

      -- Window
      Window := Gtk_Window (Builder.Get_Object ("Window"));
      Window.On_Destroy (Destroy_Event_Callback'Access);
      Window.Show_All;

      -- Start the main event loop
      Gtk.Main.Main;

   end Run;


   ----------------------------
   -- Destroy_Event_Callback --
   ----------------------------

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class)
   is
   begin
      Gtk.Main.Main_Quit;
   end Destroy_Event_Callback;

   ----------------------------
   -- Clicked_Event_Callback --
   ----------------------------

   procedure Clicked_Event_Callback
     (Button : access Gtk.Button.Gtk_Button_Record'Class) is
   begin

      declare
         Response : String :=
                      Gtkada.File_Selection.File_Selection_Dialog
                        (Title       => "Select your file",
                         Default_Dir => "",
                         Dir_Only    => False,
                         Must_Exist  => True);
      begin
         GEntry.Set_Text (Response);
      end;

   end Clicked_Event_Callback;

end File_Selection_Demo;

example.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<interface>
  <requires lib="gtk+" version="3.10"/>
  <object class="GtkWindow" id="Window">
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">GTK File Selector Demo</property>
    <property name="resizable">False</property>
    <property name="window_position">center</property>
    <child>
      <object class="GtkBox" id="HBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkEntry" id="Entry">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="margin_left">10</property>
            <property name="margin_right">10</property>
            <property name="margin_top">5</property>
            <property name="margin_bottom">5</property>
            <property name="hexpand">True</property>
            <property name="editable">False</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="Button">
            <property name="label" translatable="yes">Choose File...</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="margin_left">10</property>
            <property name="margin_right">12</property>
            <property name="margin_top">5</property>
            <property name="margin_bottom">5</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

【讨论】:

  • 特定的Program_Error 很可能是由未处理的 kernel 信号引起的。查看更新的答案。
  • 这是我提出错误strace: Process 12811 attached --- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=12811, si_uid=1000} ---时的 strace 输出@
  • 你的例子和我的代码的结果是一样的。
  • 与 Gtkada 2019 和 Gnat 2019 的结果相同。
  • SIGABRT 信号可能是由于libc 中的致命错误(请参阅here)。您或许可以验证这一点(请参阅 here),但这不太可能导致您找到解决方案。我在这里猜测,但可能存在库版本冲突。你能检查一下安装了哪个版本的 GTK 吗?在 Fedora 上,我认为你可以通过 rpm -q gtk2 和/或 rpm -q gtk3 来做到这一点。
猜你喜欢
  • 2015-09-04
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多