【问题标题】:Trouble hiding and showing widgets in response to event无法响应事件隐藏和显示小部件
【发布时间】:2015-04-20 08:07:12
【问题描述】:

问题

我有一个问题,即通过 gtk_widget_hide_on_delete 关闭带有删除事件的小部件无法通过交换的 gtk_widget_show_all 再次显示菜单小部件,并将相应的小部件作为参数传递给它。

背景

我正在创建一个程序,该程序由一个带有许多按钮小部件的选择菜单组成。按一个按钮将隐藏菜单,并显示一个包含标签和 TextEntry 的窗口小部件,该窗口小部件的删除事件将隐藏该小部件,并再次显示菜单。

示例程序

我为这个问题创建了一个最小的例子。代码简单地通过GtkBuilder加载ui,然后进入gtk主循环。

我依赖gtk_widget_show_allgtk_widget_hidegtk_widget_hide_on_delete,但是当我使用delete-event 关闭运动小部件时,窗口消失了,但菜单小部件没有显示.

#include <gtk/gtk.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    GtkBuilder * builder;
    GtkWidget * menu;
    GError *error = NULL;

    gtk_init(&argc, &argv);
    builder = gtk_builder_new();
    if (!gtk_builder_add_from_file(builder, "example.glade", &error)) {
        g_warning("%s", error->message);
        g_free(error);
        fprintf(stderr, "Failed to load build file");
    }

    menu = (GtkWidget *) gtk_builder_get_object(builder, "menu");
  
    gtk_builder_connect_signals(builder, NULL);
    gtk_widget_show(menu);

    gtk_main();
  
    return 0;
}

XML 文件 example.glade 是使用 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="exercise">
    <property name="can_focus">False</property>
    <property name="window_position">center</property>
    <signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/>
    <signal name="delete-event" handler="gtk_widget_show_all" object="menu" after="yes" swapped="yes"/>
    <child>
      <object class="GtkGrid" id="grid2">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkEntry" id="entry1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="hexpand">True</property>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">1</property>
            <property name="width">1</property>
            <property name="height">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <property name="label" translatable="yes">A window where stuff will happen.</property>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">0</property>
            <property name="width">1</property>
            <property name="height">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
  <object class="GtkWindow" id="menu">
    <property name="can_focus">False</property>
    <property name="window_position">center</property>
    <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
    <child>
      <object class="GtkGrid" id="grid1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkButton" id="button1">
            <property name="label" translatable="yes">button1</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <signal name="clicked" handler="gtk_widget_hide" object="menu" swapped="yes"/>
            <signal name="clicked" handler="gtk_widget_show_all" object="exercise" swapped="yes"/>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">0</property>
            <property name="width">1</property>
            <property name="height">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="button2">
            <property name="label" translatable="yes">button2</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <signal name="clicked" handler="gtk_widget_hide" object="menu" swapped="yes"/>
            <signal name="clicked" handler="gtk_widget_show_all" object="exercise" swapped="yes"/>
          </object>
          <packing>
            <property name="left_attach">0</property>
            <property name="top_attach">1</property>
            <property name="width">1</property>
            <property name="height">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

【问题讨论】:

    标签: c xml user-interface gtk3


    【解决方案1】:

    问题出在 Glade 文件的这两行:

    <signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/>
    <signal name="delete-event" handler="gtk_widget_show_all" object="menu" after="yes" swapped="yes"/>
    

    查看gtk_widget_hide_on_delete()manual page,我们看到:

    实用功能;旨在连接到 GtkWindow 上的“删除事件”信号。该函数在其参数上调用gtk_widget_hide(),然后返回TRUE

    如果我们查看delete-event 信号,我们会看到:

    返回

    TRUE 阻止为该事件调用其他处理程序。 FALSE 进一步传播事件。

    这意味着在调用gtk_widget_hide_on_delete() 之后,会返回TRUE,这会阻止GTK 运行时调用gtk_widget_show_all()

    要实现你想要的,你可以使用自定义的处理程序,如下所示:

    1. 删除这两行并替换为以下内容:

      <signal name="delete-event" handler="my_custom_func" object="menu" swapped="no"/>
      
    2. 将您的自定义处理程序添加到 C 文件:

      G_MODULE_EXPORT gboolean
      my_custom_func(GtkWidget *w, GdkEvent *e, gpointer u) {
          gtk_widget_hide(w);
          gtk_widget_show_all(GTK_WIDGET(u));
          return TRUE;
      }
      

    【讨论】:

    • @LeonhardPrintz 您可以通过单击此帖子左侧的绿色复选标记将此答案标记为“已接受”。
    • 顺便说一句,我如何在发布代码时获得语法高亮显示? (下次我发布问题时)我希望它尽可能可读,这是我的第一篇文章,所以我可能会比需要的时间长一点。
    猜你喜欢
    • 1970-01-01
    • 2011-09-16
    • 2017-06-18
    • 2017-10-11
    • 1970-01-01
    • 2017-04-25
    • 2014-03-09
    • 2021-01-17
    • 1970-01-01
    相关资源
    最近更新 更多