GTK3 中的可滚动布局

Scrollable layout in GTK3

我正在尝试使用 GTK(准确地说是 GTK 3)编写 C 程序(到目前为止,我的经验主要是使用 ObjC、Visual Studio 等等,但跨平台 FTW !)

我需要一个可滚动的 table,所以我一直在研究我在网上找到的一些示例代码。到目前为止,我能够找到的唯一 table 代码会增加 window,并在添加行时将任何其他元素向下推到屏幕下方。我需要 table 为固定大小并滚动(当然,使 header 行可见)。

这是我目前得到的:

#include <gtk/gtk.h>

enum {
    FILE_NAME,
    FILE_OFFSET,
    FILE_SIZE,
    FILE_DESCRIPTION, /* Not used by the view, maybe used elsewhere */
    COLOR,            /* Just to show how the model can affect the view */
    N_COLUMNS
};

void add_row (GtkWidget *widget, gpointer data) {
    gtk_list_store_insert_with_values(data, NULL, -1,
                                       COLOR, "blue",
                                       -1);

}

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

gint main(gint argc, gchar **argv)
{
    GtkListStore*      model;
    GtkWidget*         view;
    GtkTreeViewColumn* column;

    gtk_init(&argc, &argv);

    /* MODEL */
    model = gtk_list_store_new(N_COLUMNS,
                               G_TYPE_STRING,   /* FILE_NAME */
                               G_TYPE_UINT,     /* FILE_OFFSET */
                               G_TYPE_UINT,     /* FILE_SIZE */
                               G_TYPE_STRING,   /* FILE_DESCRIPTION */
                               G_TYPE_STRING    /* COLOR */
                              );
    gtk_list_store_insert_with_values(model, NULL, -1,
                                      FILE_NAME, "test name",
                                      FILE_OFFSET, 0,
                                      FILE_SIZE, 10,
                                      -1);
    gtk_list_store_insert_with_values(model, NULL, -1,
                                      FILE_NAME, "Dummy",
                                      FILE_OFFSET, 123,
                                      COLOR, "black",
                                      -1);

    /* VIEW */
    view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));

    g_object_unref(model);

    column = gtk_tree_view_column_new_with_attributes("Name",
                                                      gtk_cell_renderer_text_new(),
                                                      "text", FILE_NAME,
                                                      "background", COLOR,
                                                      NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);

    column = gtk_tree_view_column_new_with_attributes("Offset",
                                                      gtk_cell_renderer_spin_new(),
                                                      "text", FILE_OFFSET,
                                                      NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);

    column = gtk_tree_view_column_new_with_attributes("Size",
                                                      gtk_cell_renderer_text_new(),
                                                      "text", FILE_SIZE,
                                                      NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);


    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Test App");
    gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
    g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);

    /* Button */
    GtkWidget *button;
    button = gtk_button_new_with_label ("Add row");
    g_signal_connect (button, "clicked", G_CALLBACK(add_row), model);

    /* Layoutbox */
    GtkWidget *layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
    gtk_container_add (GTK_CONTAINER (window), layout_box);

    /* Scrollview */
    GtkWidget *scrollview = gtk_layout_new(NULL, NULL);
    g_object_set(G_OBJECT(scrollview), "app-paintable", TRUE, NULL);
    gtk_widget_add_events (scrollview, GDK_ALL_EVENTS_MASK);
    gtk_layout_put (GTK_LAYOUT (scrollview), view, 10, 10);
    gtk_widget_set_size_request(view, 300, 200);


    gtk_container_add (GTK_CONTAINER (layout_box), scrollview); //view
    gtk_widget_show_all(window);

    GdkWindow *win = gtk_layout_get_bin_window (GTK_LAYOUT(scrollview));
    gdk_window_set_events (win, gdk_window_get_events (win) | GDK_STRUCTURE_MASK);

    gtk_main ();

    return 0;
}

目前有点乱!抱歉 - 部分原因是我对 GTK 缺乏经验,主要是多次迭代试图让它工作。

目前 table 在消失之前显示的时间非常短(这种有趣的行为只有在我尝试将其变成滚动框时才出现)。

请注意,我只希望 table 滚动 - 而不是整个 window。在一个完美的世界中,table 将是 window(或包含它的布局)的宽度,但限制为 n 像素高,如果高度超过该限制,则带有滚动条。

虽然我是一个简单的人,所以我也希望任何解决方案都简单 - 这样我就可以全神贯注!

有什么想法吗?

您正在使用 GtkLayout,但用于滚动的小部件是 GtkScrolledWindow

这是修改后的代码:

#include <gtk/gtk.h>

enum {
    FILE_NAME,
    FILE_OFFSET,
    FILE_SIZE,
    FILE_DESCRIPTION, /* Not used by the view, maybe used elsewhere */
    COLOR,            /* Just to show how the model can affect the view */
    N_COLUMNS
};

void add_row (GtkWidget *widget, gpointer data) {
    gtk_list_store_insert_with_values(data, NULL, -1,
                                       COLOR, "blue",
                                       -1);

}

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

gint main(gint argc, gchar **argv)
{
    GtkListStore*      model;
    GtkWidget*         view;
    GtkTreeViewColumn* column;

    gtk_init(&argc, &argv);

    /* MODEL */
    model = gtk_list_store_new(N_COLUMNS,
                               G_TYPE_STRING,   /* FILE_NAME */
                               G_TYPE_UINT,     /* FILE_OFFSET */
                               G_TYPE_UINT,     /* FILE_SIZE */
                               G_TYPE_STRING,   /* FILE_DESCRIPTION */
                               G_TYPE_STRING    /* COLOR */
                              );
    gtk_list_store_insert_with_values(model, NULL, -1,
                                      FILE_NAME, "test name",
                                      FILE_OFFSET, 0,
                                      FILE_SIZE, 10,
                                      -1);
    gtk_list_store_insert_with_values(model, NULL, -1,
                                      FILE_NAME, "Dummy",
                                      FILE_OFFSET, 123,
                                      COLOR, "black",
                                      -1);

    /* VIEW */
    view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));

    g_object_unref(model);

    column = gtk_tree_view_column_new_with_attributes("Name",
                                                      gtk_cell_renderer_text_new(),
                                                      "text", FILE_NAME,
                                                      "background", COLOR,
                                                      NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);

    column = gtk_tree_view_column_new_with_attributes("Offset",
                                                      gtk_cell_renderer_spin_new(),
                                                      "text", FILE_OFFSET,
                                                      NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);

    column = gtk_tree_view_column_new_with_attributes("Size",
                                                      gtk_cell_renderer_text_new(),
                                                      "text", FILE_SIZE,
                                                      NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);


    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Test App");
    gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
    g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);

    /* Button */
    GtkWidget *button;
    button = gtk_button_new_with_label ("Add row");
    g_signal_connect (button, "clicked", G_CALLBACK(add_row), model);

    /* Layoutbox */
    GtkWidget *layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
    gtk_container_add (GTK_CONTAINER (window), layout_box);

    /* Scrollview */
    GtkWidget *scrollview = gtk_scrolled_window_new(NULL, NULL);
    gtk_container_add (GTK_CONTAINER (scrollview), view);
    /* expand to fill all available space left in the window */
    gtk_widget_set_hexpand(scrollview, TRUE);
    gtk_widget_set_vexpand(scrollview, TRUE);


    gtk_container_add (GTK_CONTAINER (layout_box), scrollview); //view
    gtk_container_add (GTK_CONTAINER (layout_box), button);
    gtk_widget_show_all(window);

    gtk_main ();

    return 0;
}