2009-11-17 48 views
11

Tôi đã phát triển một cửa sổ bật lên (Không được trang trí) bằng GTK + và công cụ lấp lánh trong C. Nó bật lên trên cửa sổ chính khi nút được nhấp. Tôi muốn hủy hoặc ẩn cửa sổ bật lên này khi người dùng nhấp vào bên cạnh cửa sổ này. Người dùng có thể nhấp vào cửa sổ cha hoặc bất kỳ cửa sổ nào khác. Tôi đã cố chụp GDK_FOCUS_CHANGE sự kiện nhưng tôi không thể nắm bắt sự kiện này. Có bất kì cách nào để đạt được điều này không? Làm thế nào để tôi biết rằng nhấp chuột là trên cửa sổ khác sau đó bật lên cửa sổ? Làm thế nào là nó rõ ràng rằng cửa sổ bật lên đã mất tập trung của nó? Để tôi có thể ẩn nó. Mã liên quan như sau:Cách ẩn Cửa sổ bật lên Gtk khi người dùng nhấp vào bên ngoài cửa sổ

/* 
* 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; 
} 

Ở đây tôi không thể để ẩn cửa sổ pop này lên cửa sổ khi người dùng nhấp vào cửa sổ cha mẹ hoặc trên cửa sổ khác. Tôi có thể làm cái này như thế nào?

Tôi phải gắn bó với phiên bản Gtk + 2.14.

+0

Vui lòng không trả lời câu hỏi. Điều này có vẻ là một sự lặp lại tốt hơn (được trình bày tốt hơn) của http://stackoverflow.com/questions/1740947/problem-with-gtk-popup-window-focus-change-event-handling – mlibby

+0

Tôi sẽ chăm sóc điều này trong tương lai. – kbalar

Trả lời

8

Thay đổi:

  • switch GTK_WINDOW_POPUP-GTK_WINDOW_TOPLEVEL, phản trực giác, nhưng tôi không thể tìm ra cách để có được một popup để chấp nhận tập trung.
  • thêm gtk_window gợi ý để ngăn chặn cửa sổ bật lên hiển thị trong thanh tác vụ và pager
  • cố ý đặt tiêu điểm trên cửa sổ popup
  • thiết lập GDK_FOCUS_CHANGE_MASK trên GDK_WINDOW với gtk_widget_set_events (yêu cầu cho các bước tiếp theo)
  • kết nối với focus-out-event của cửa sổ popup
  • thay đổi xử lý tín hiệu để xử lý tín hiệu khác nhau

tôi woul d cũng khuyên bạn nên đọc nguồn GTK + để xem cách xử lý cửa sổ bật lên cho chú giải công cụ và menu khi chúng được hiển thị ... nhưng chúng thường bị phá hủy dựa trên chuột di chuyển ngoài phạm vi, không phải cửa sổ bật lên mất tiêu điểm.


#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; 
} 
+0

Đã làm việc !! Cảm ơn bạn đã xem xét điều này. – kbalar

+0

Giải quyết tốt. Nếu câu trả lời này phù hợp với bạn, vui lòng nhấp vào dấu kiểm lớn bên cạnh câu trả lời.:) – mlibby

+0

Giải pháp tuyệt vời, nhưng có một vấn đề: Cửa sổ chính là đăng ký trực quan các thay đổi tiêu điểm bằng cách tô màu đường viền khác nhau (Windows 7). Điều này không nên xảy ra cho một cửa sổ popup (giả). Bất kỳ ý tưởng để ngăn chặn điều này? – schlamar

2

Bạn không cần đặt trọng tâm bàn phím vào cửa sổ bật lên của mình.

Bạn chỉ cần chụp chuột đến popup_window->window sử dụng gdk_pointer_grab(...) với các đối số True owner_events và GDK_BUTTON_PRESS_MASK GdkEventMask.

Sau đó, kết nối popup_window của bạn với "button-press-event". Bên trong xử lý của nó ẩn/phá hủy popup_window của bạn và phát hành chụp bằng cách sử dụng gdk_pointer_ungrab(...) nếu * sự kiện tọa độ là tiêu cực hoặc cao hơn kích thước popup_window của bạn.

1

Một giải pháp thay thế khác là chỉ cần thêm người nghe nhấn nút vào cửa sổ chính. Điều này có lợi thế là cửa sổ bật lên vẫn trông giống như cửa sổ bật lên (cả bố và mẹ đều có thể hoạt động cùng một lúc)

#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); 
} 
Các vấn đề liên quan