GTK ScrolledWindow 仅在 Scrollbar 显示一次后显示内容

问题描述 投票:0回答:0

我使用 GTK+3 C API 编写了一个程序。它应该在左上角显示一个黑色绘图区域。如果窗口大于绘图区域,则窗口应具有“空填充”,否则允许在绘图区域内滚动。

但是,如果窗口最初大于绘图区域,它将不会显示绘图区域,直到窗口被调整为小于绘图区域的大小。

代码如下:

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

int current_frame_x = 200;
int current_frame_y = 300;

gint max(gint a, gint b) {
    return a > b ? a : b;
}

gint min(gint a, gint b) {
    return a < b ? a : b;
}

static void on_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer /*user_data*/) {
    // Get the new size of the window
    gint parent_width = allocation->width;
    gint parent_height = allocation->height;

    int draw_x = min(current_frame_x, parent_width);
    int draw_y = min(current_frame_y, parent_height);
    int exceeding_x = max(parent_width - draw_x, 0);
    int exceeding_y = max(parent_height - draw_y, 0);

    // Get the child widgets of the grid
    GtkWidget *upper_left = gtk_grid_get_child_at(GTK_GRID((widget)), 0, 0);
    GtkWidget *upper_right = gtk_grid_get_child_at(GTK_GRID((widget)), 1, 0);
    GtkWidget *lower_left = gtk_grid_get_child_at(GTK_GRID((widget)), 0, 1);
    GtkWidget *lower_right = gtk_grid_get_child_at(GTK_GRID((widget)), 1, 1);

    // Set the new sizes of the cells
    assert(upper_left);
    GtkAllocation upper_left_alloc;
    upper_left_alloc.x = allocation->x;
    upper_left_alloc.y = allocation->y;
    upper_left_alloc.width = draw_x;
    upper_left_alloc.height = draw_y;
    gtk_widget_size_allocate(upper_left, &upper_left_alloc);

    if (upper_right) {
        GtkAllocation upper_right_alloc;
        upper_right_alloc.x = allocation->x + draw_x;
        upper_right_alloc.y = allocation->y;
        upper_right_alloc.width = exceeding_x;
        upper_right_alloc.height = draw_y;
        gtk_widget_size_allocate(upper_right, &upper_right_alloc);
    }

    if (upper_left) {
        GtkAllocation lower_left_alloc;
        lower_left_alloc.x = allocation->x;
        lower_left_alloc.y = allocation->y + draw_y;
        lower_left_alloc.width = draw_x;
        lower_left_alloc.height = exceeding_y;
        gtk_widget_size_allocate(lower_left, &lower_left_alloc);
    }

    if (lower_right) {
        GtkAllocation lower_right_alloc;
        lower_right_alloc.x = allocation->x + draw_x;
        lower_right_alloc.y = allocation->y + draw_y;
        lower_right_alloc.width = exceeding_x;
        lower_right_alloc.height = exceeding_y;
        gtk_widget_size_allocate(lower_right, &lower_right_alloc);
    }
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);

    // Create the main window
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Hello Stack Overflow :)");
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    // Create the drawing area
    GtkWidget *drawing_area = gtk_drawing_area_new();
    gtk_widget_set_size_request(drawing_area, current_frame_x, current_frame_y);

    // Set the background color of the drawing area (for debugging)
    GdkRGBA color;
    color.red = 1;
    color.green = 1;
    color.blue = 1;
    color.alpha = 1;
    gtk_widget_override_background_color(drawing_area, GTK_STATE_FLAG_NORMAL, &color);

    // Wrap the drawing area in a scroll window
    GtkWidget *scroll_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_container_add(GTK_CONTAINER(scroll_window), drawing_area);
    gtk_widget_show(scroll_window); 

    GtkWidget *tmp_h_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    GtkWidget *tmp_v_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    GtkWidget *other_tmp_v_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); 


    // Wrap the scroll window in a grid for resizing
    GtkWidget *draw_grid = gtk_grid_new();
    gtk_grid_attach(GTK_GRID(draw_grid), scroll_window, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(draw_grid), tmp_h_box, 0, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(draw_grid), tmp_v_box, 1, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(draw_grid), other_tmp_v_box, 1, 1, 1, 1); 

    gtk_grid_set_column_homogeneous(GTK_GRID(draw_grid), FALSE);
    gtk_grid_set_row_homogeneous(GTK_GRID(draw_grid), FALSE);
    gtk_widget_set_hexpand(draw_grid, TRUE);
    gtk_widget_set_vexpand(draw_grid, TRUE);
    g_signal_connect(draw_grid, "size-allocate", G_CALLBACK(on_size_allocate), NULL);

    gtk_container_add(GTK_CONTAINER(window), draw_grid);
    gtk_widget_show_all(window);

    gtk_main();
    return 0;
}

想法是使用网格来处理这个。我让网格通过

hexpand
vexpand
扩展,并通过监听
size-allocate
的函数手动设置其子项的大小。从交互式调试器和一些调试打印来看,所有大小计算似乎都是正确的。框和绘图区域似乎放置在我想要的位置并且大小合适。当窗口变大时,绘图区域最初是不可见的。 (即使调试器显示空间已分配。)

也可能(和更好的解决方案)只使用一个容器并使用滚动窗口的对齐属性将其放在左上角。但我对此并不陌生,所以让我先了解这里出了什么问题。

c gtk gtk3
© www.soinside.com 2019 - 2024. All rights reserved.