我在C中使用GTK +和glade工具开发了一个弹出窗口(非装饰)。
单击一个按钮时,它会在其父窗口中弹出。我想在用户点击此窗口时销毁或隐藏此弹出窗口。用户可以单击父窗口或任何其他窗口。
我试图抓住 GDK_FOCUS_CHANGE
事件,但我无法捕获此事件。有没有办法实现这个目标?我怎么知道点击是在其他窗口然后弹出窗口?怎么清楚弹出窗口已经失去了它的焦点?
所以我可以隐藏它。
相关代码如下:
/*
* Compile me with:
gcc -o popup popup.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)
*/
#include <gtk/gtk.h>
static void on_popup_clicked (GtkButton*, GtkWidget*);
static gboolean on_popup_window_event(GtkWidget*, GdkEventExpose*);
int main (int argc, char *argv[])
{
GtkWidget *window, *button, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Parent window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 300);
gtk_window_set_position (GTK_WINDOW (window),GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label("Pop Up");
g_signal_connect (G_OBJECT (button), "clicked",G_CALLBACK (on_popup_clicked),(gpointer) window);
vbox = gtk_vbox_new (FALSE, 3);
gtk_box_pack_end(GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void on_popup_clicked (GtkButton* button, GtkWidget* pWindow)
{
GtkWidget *popup_window;
popup_window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_title (GTK_WINDOW (popup_window), "Pop Up window");
gtk_container_set_border_width (GTK_CONTAINER (popup_window), 10);
gtk_window_set_resizable(GTK_WINDOW (popup_window), FALSE);
gtk_window_set_decorated(GTK_WINDOW (popup_window), FALSE);
gtk_widget_set_size_request (popup_window, 150, 150);
gtk_window_set_transient_for(GTK_WINDOW (popup_window),GTK_WINDOW (pWindow));
gtk_window_set_position (GTK_WINDOW (popup_window),GTK_WIN_POS_CENTER);
g_signal_connect (G_OBJECT (button), "event",
G_CALLBACK (on_popup_window_event),NULL);
GdkColor color;
gdk_color_parse("#3b3131", &color);
gtk_widget_modify_bg(GTK_WIDGET(popup_window), GTK_STATE_NORMAL, &color);
gtk_widget_show_all (popup_window);
}
gboolean on_popup_window_event(GtkWidget *popup_window, GdkEventExpose *event)
{
if(event->type == GDK_FOCUS_CHANGE)
gtk_widget_hide (popup_window);
return FALSE;
}
在用户单击父窗口或其他窗口时,我无法隐藏此弹出窗口。我怎样才能做到这一点?
我必须坚持使用Gtk + 2.14版本。
变化:
- 切换自
GTK_WINDOW_POPUP
至 GTK_WINDOW_TOPLEVEL
反直觉,但我无法弄清楚如何让弹出窗口接受焦点。
- 加
gtk_window
提示阻止弹出窗口显示在任务栏和寻呼机中
- 故意将焦点放在弹出窗口上
- 设置
GDK_FOCUS_CHANGE_MASK
在...上 GDK_WINDOW
同 gtk_widget_set_events
(下一步所需)
- 连接到
focus-out-event
弹出窗口
- 更改信号处理程序以处理不同的信号
我还建议阅读GTK +源,看看它在显示时如何处理工具提示和菜单的弹出窗口......但是这些通常是基于鼠标移出范围而不是弹出失去焦点本身而被破坏。
#include
static void on_popup_clicked (GtkButton*, GtkWidget*);
gboolean on_popup_focus_out (GtkWidget*, GdkEventFocus*, gpointer);
int
main (int argc, char *argv[])
{
GtkWidget *window, *button, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Parent window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 300);
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label ("Pop Up");
g_signal_connect (G_OBJECT (button),
"clicked",
G_CALLBACK (on_popup_clicked),
(gpointer) window);
vbox = gtk_vbox_new (FALSE, 3);
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void
on_popup_clicked (GtkButton* button, GtkWidget* pWindow)
{
GtkWidget *popup_window;
popup_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (popup_window), "Pop Up window");
gtk_container_set_border_width (GTK_CONTAINER (popup_window), 10);
gtk_window_set_resizable (GTK_WINDOW (popup_window), FALSE);
gtk_window_set_decorated (GTK_WINDOW (popup_window), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (popup_window), TRUE);
gtk_window_set_skip_pager_hint (GTK_WINDOW (popup_window), TRUE);
gtk_widget_set_size_request (popup_window, 150, 150);
gtk_window_set_transient_for (GTK_WINDOW (popup_window), GTK_WINDOW (pWindow));
gtk_window_set_position (GTK_WINDOW (popup_window), GTK_WIN_POS_CENTER);
gtk_widget_set_events (popup_window, GDK_FOCUS_CHANGE_MASK);
g_signal_connect (G_OBJECT (popup_window),
"focus-out-event",
G_CALLBACK (on_popup_focus_out),
NULL);
GdkColor color;
gdk_color_parse ("#3b3131", &color);
gtk_widget_modify_bg (GTK_WIDGET (popup_window), GTK_STATE_NORMAL, &color);
gtk_widget_show_all (popup_window);
gtk_widget_grab_focus (popup_window);
}
gboolean
on_popup_focus_out (GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
gtk_widget_destroy (widget);
return TRUE;
}
您无需将键盘焦点设置到弹出窗口。
你只需要捕捉鼠标 popup_window->window
运用 gdk_pointer_grab(...)
真的 owner_events
和GDK_BUTTON_PRESS_MASK GdkEventMask
参数。
然后将popup_window连接到 "button-press-event"
。在它的处理程序中隐藏/破坏你的popup_window并使用释放捕获 gdk_pointer_ungrab(...)
如果*事件坐标为负或高于popup_window大小。
另一种方法是简单地将按钮监听器添加到父窗口。这样做的好处是弹出窗口仍然看起来像弹出窗口(父窗口和它自己都可以立即激活)
#include <stdio.h>
#include <gtk/gtk.h>
static void on_popup_clicked (GtkButton*, GtkWidget*);
gulong handler_id;
gboolean
on_click (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
g_signal_handler_disconnect (widget, handler_id);
gtk_widget_destroy (user_data);
return TRUE;
}
gboolean
on_popup_focus_out (GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
gtk_widget_destroy (widget);
return TRUE;
}
int
main (int argc, char *argv[])
{
GtkWidget *window, *button, *vbox;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Parent window");
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_set_size_request (window, 300, 300);
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label ("Pop Up");
g_signal_connect (G_OBJECT (button),
"clicked",
G_CALLBACK (on_popup_clicked),
(gpointer) window);
vbox = gtk_vbox_new (FALSE, 3);
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
void
on_popup_clicked (GtkButton* button, GtkWidget* pWindow)
{
GtkWidget *popup_window;
popup_window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_title (GTK_WINDOW (popup_window), "Pop Up window");
gtk_container_set_border_width (GTK_CONTAINER (popup_window), 10);
gtk_window_set_resizable (GTK_WINDOW (popup_window), FALSE);
gtk_window_set_decorated (GTK_WINDOW (popup_window), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (popup_window), TRUE);
gtk_window_set_skip_pager_hint (GTK_WINDOW (popup_window), TRUE);
gtk_widget_set_size_request (popup_window, 150, 150);
gtk_window_set_transient_for (GTK_WINDOW (popup_window), GTK_WINDOW (pWindow));
gtk_window_set_position (GTK_WINDOW (popup_window), GTK_WIN_POS_CENTER);
gtk_widget_add_events (popup_window, GDK_FOCUS_CHANGE_MASK);
gtk_widget_add_events (pWindow, GDK_BUTTON_PRESS_MASK);
g_signal_connect (G_OBJECT (popup_window),
"focus-out-event",
G_CALLBACK (on_popup_focus_out),
NULL);
handler_id = g_signal_connect (G_OBJECT (pWindow),
"button-press-event",
G_CALLBACK (on_click),
popup_window);
GdkColor color;
gdk_color_parse ("#3b3131", &color);
gtk_widget_modify_bg (GTK_WIDGET (popup_window), GTK_STATE_NORMAL, &color);
gtk_widget_show_all (popup_window);
gtk_widget_grab_focus (popup_window);
}