gtk在對話框中顯示一個對話框

[英]gtk displaying a dialog from within a dialog


I'm writing a gtk program, at some point in my application, I call a gtkdialog to obtain input from the user. what I want to do is close the current dialog and open another dialog when the OK button is clicked, I already have a function doing some other work, starting the dialog in that function would be great. here's the parent dialog code:

我正在編寫一個gtk程序,在我的應用程序中的某個時刻,我調用gtkdialog來獲取用戶的輸入。我想要做的是關閉當前對話框並在單擊確定按鈕時打開另一個對話框,我已經有一個功能做其他工作,在該功能中啟動對話框會很棒。這是父對話框代碼:

GtkWidget * new_button_dialog = gtk_dialog_new_with_buttons("new button",(GtkWindow *)container,GTK_DIALOG_DESTROY_WITH_PARENT,"OK", GTK_RESPONSE_OK,NULL);
       GtkWidget * content_area = gtk_dialog_get_content_area (GTK_DIALOG (new_button_dialog));
       GtkWidget * button_name_label = gtk_label_new ("Press escape at any time to cancel.\ntype in the button name");
       gtk_container_add (GTK_CONTAINER (content_area) , button_name_label);
       GtkWidget * button_name_entry = gtk_entry_new();
       gtk_entry_set_activates_default((GtkEntry*)button_name_entry,TRUE);
       gtk_container_add(GTK_CONTAINER(content_area), button_name_entry);
       GtkWidget * button_text_dialog = gtk_dialog_new_with_buttons("new button",(GtkWindow *)container,GTK_DIALOG_DESTROY_WITH_PARENT,"OK", GTK_RESPONSE_OK,NULL);
      gtk_container_add (GTK_CONTAINER (container), button);
       g_signal_connect(new_button_dialog,"response",G_CALLBACK (add_new_button),NULL);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",GTK_SIGNAL_FUNC (gtk_widget_show_all),(GtkWidget*)new_button_dialog);
       gtk_widget_show_all((GtkWidget *)container);

1 个解决方案

#1


2  

The response of a dialog cannot be handled in the same function that the dialog is created. It means that in one function you cannot create a dialog, handle its input, close that dialog and open a new dialog. It cannot be done since when that function exits the dialog entry is empty and the first dialog is just shown.

無法在創建對話框的同一函數中處理對話框的響應。這意味着在一個函數中,您無法創建對話框,處理其輸入,關閉該對話框並打開新對話框。當該函數退出對話框條目為空並且僅顯示第一個對話框時,無法完成。

It should be done as a chain of separate event handlers. All needed variables (data context) should be transferred between those separate handlers using a pointer to structure that holds that context.

它應該作為一系列獨立的事件處理程序來完成。應使用指向保存該上下文的結構的指針在這些單獨的處理程序之間傳輸所有需要的變量(數據上下文)。

The below full runnable example demonstrates such flow.

以下完整的可運行示例演示了此類流程。

In the fist dialog handler we want to do something with the main window and some container object and maybe we want some other data that is shared between widgets of that main window. The structure window_ctx_t is declared for such context. There is a boolean flag in that context to lock creation on new dialog chains before closing active dialogs.

在第一個對話框處理程序中,我們想要對主窗口和一些容器對象做一些事情,也許我們想要在該主窗口的窗口小部件之間共享一些其他數據。為此類上下文聲明了結構window_ctx_t。在關閉活動對話框之前,該上下文中有一個布爾標志用於鎖定新對話鏈上的創建。

The function first_dialog_create creates the first dialog with text entry field. It receives window_ctx_t, where the main window pointer is stored that is used for the dialog creation. Now we need to attach to that dialog response handler and provide to the handler enough data for its functionality. In that example we provide pointer to text entry that is used to read text.

函數first_dialog_create創建帶有文本輸入字段的第一個對話框。它接收window_ctx_t,其中存儲用於對話創建的主窗口指針。現在我們需要附加到該對話框響應處理程序,並為處理程序提供足夠的數據以實現其功能。在該示例中,我們提供指向用於讀取文本的文本條目的指針。

Using provided data the response handler add_new_button is able to read text entry, to create a new dialog attached to the main window and also to do something with provided container.

使用提供的數據,響應處理程序add_new_button能夠讀取文本條目,創建一個附加到主窗口的新對話框,還可以使用提供的容器執行某些操作。

When the first dialog data context is not needed it is freed by calling g_free() in the dialog destroyed handler.

當不需要第一個對話框數據上下文時,通過在對話框銷毀的處理程序中調用g_free()來釋放它。

Build the example:

建立示例:

gcc -Wall -g dialogs.c -o dialogs `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`

Example "dialogs.c"

#include <gtk/gtk.h>

typedef struct {
    GtkWidget *container;
    GtkWindow *window;
    gboolean dialogs_created;
} window_ctx_t;

typedef struct {
    GtkEntry *entry;
    window_ctx_t *window_ctx;
} first_dialog_data_t;

static void first_dialog_create(gpointer context);

static void another_dialog_response(GtkWidget *dialog, gint response_id,
    gpointer ctx)
{
    window_ctx_t *win_ctx = ctx;

    gtk_widget_destroy(dialog);
    win_ctx->dialogs_created = FALSE;
}

static void cleanup_first_dialog(GtkWidget *widget, gpointer data)
{
    g_free(data);
}

/* response callback of the first dialog */
static void add_new_button(GtkWidget *dialog, gint response_id,
    gpointer ctx)
{
    GtkWidget *button;
    GtkWidget *button_text_dialog;
    first_dialog_data_t *data = ctx;

    if (response_id != GTK_RESPONSE_OK) {
        data->window_ctx->dialogs_created = FALSE;
        goto Exit;
    }

    /* Create a new button with the label from text entry */
    button = gtk_button_new_with_label(gtk_entry_get_text(data->entry));
    /* When the button receives the "clicked" signal, it will again open
     * "new button" dialog */
    g_signal_connect_swapped(button, "clicked", G_CALLBACK(first_dialog_create),
        data->window_ctx);
    /* add button to the container */
    gtk_container_add(GTK_CONTAINER(data->window_ctx->container), button);
    /* show button */
    gtk_widget_show(button);

    /* create another dialog */
    button_text_dialog = gtk_dialog_new_with_buttons("new button",
        data->window_ctx->window, GTK_DIALOG_DESTROY_WITH_PARENT, "OK",
        GTK_RESPONSE_OK, NULL);
    g_signal_connect(button_text_dialog, "response",
        G_CALLBACK(another_dialog_response), (gpointer)data->window_ctx);

    gtk_widget_show_all(button_text_dialog);

Exit:
    gtk_widget_destroy(dialog);
}

static void first_dialog_create(gpointer context)
{
    first_dialog_data_t *data;
    window_ctx_t *win_ctx = context;

    if (win_ctx->dialogs_created)
        return;

    /* lock buttons handler */
    win_ctx->dialogs_created = TRUE;

    /* allocate structure for dialog context */
    data = g_new0(first_dialog_data_t, 1);

    /* create first dialog, its label and text entry */
    GtkWidget *new_button_dialog = gtk_dialog_new_with_buttons("new button",
        win_ctx->window, GTK_DIALOG_DESTROY_WITH_PARENT,"OK",
        GTK_RESPONSE_OK, NULL);

    GtkWidget *content_area = gtk_dialog_get_content_area(
    GTK_DIALOG(new_button_dialog));
    GtkWidget *button_name_label = gtk_label_new("Press escape at any time to "
        "cancel.\ntype in the button name");
    gtk_container_add(GTK_CONTAINER(content_area), button_name_label);

    GtkWidget * button_name_entry = gtk_entry_new();
    gtk_entry_set_activates_default((GtkEntry*)button_name_entry,TRUE);
    gtk_container_add(GTK_CONTAINER(content_area), button_name_entry);

    /* provide data to response handler */
    data->entry = (GtkEntry *)button_name_entry;
    data->window_ctx = win_ctx;
    g_signal_connect(new_button_dialog, "response", G_CALLBACK(add_new_button),
        data);

    /* handler to free dialog context 'data' when destroed */
    g_signal_connect(new_button_dialog, "destroy",
        G_CALLBACK(cleanup_first_dialog), data);

    /* show first dialog */
    gtk_widget_show_all(new_button_dialog);
}

static void destroy(GtkWidget *widget, gpointer data)
{
    gtk_main_quit();
}

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *box1;
    GtkWidget *button;
    window_ctx_t win_ctx;

    gtk_init (&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

    box1 = gtk_hbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), box1);

    /* set window context */
    win_ctx.window = (GtkWindow *)window;
    win_ctx.container = box1;
    win_ctx.dialogs_created = FALSE;

    g_signal_connect (window, "destroy", G_CALLBACK(destroy), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);

    button = gtk_button_new_with_label("Start");
    g_signal_connect_swapped(button, "clicked", G_CALLBACK(first_dialog_create),
        &win_ctx);
    gtk_container_add(GTK_CONTAINER(box1), button);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/10/20/710d709ce7302edbe31744cb4669aa40.html



 
  © 2014-2022 ITdaan.com 联系我们: