Как рисовать в области GTK3 с полосами прокрутки - PullRequest
0 голосов
/ 19 апреля 2020

Я создаю вложенное приложение GTK: есть GtkNotebook - GtkGrid - GtkGrid - GtkFrame - GtkDrawingArea.

В GtkDrawingArea (я фиксирую размер с помощью запроса размера) я создаю чертежи и создаю возможность для увеличения с помощью колеса прокрутки.

Логически, когда я «увеличиваю», поверхность становится больше, и для просмотра всего чертежа необходимы полосы прокрутки.

Как их получить? Я пробовал GtkLayout и GtkSrolledWindow в разных комбинациях, но они не работали. На Inte rnet.

я не нашел ни одного полезного примера. Как можно получить прокручиваемую область рисования? С чего мне начать копаться? Любые советы приветствуются!

Спасибо.

Кстати: я использую Debian, GTK3, C и Cairo

MCVE: я создал этот пример. Это dr aws прямоугольник, и вы можете увеличить его с помощью колеса прокрутки. Это происходит в кадре 300x300. Я хотел бы иметь этот кадр с полосами прокрутки. Любые идеи, как это сделать?

Этот код может быть скомпилирован с помощью

gcc `pkg-config --cflags gtk+-3.0` -lm -o cf cf.c `pkg-config --libs gtk+-3.0`

ср. c:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <gtk/gtk.h>

#define ZOOMING_STEP 1.2

typedef struct m_data
{
    double scaling_factor;
    cairo_surface_t *circle_surface_p, *final_surface_p;
    GtkWidget *window_p;
} m_data_struct;

static void activate(GtkApplication *, gpointer);
static gboolean zoom_it(GtkWidget *, GdkEvent *, gpointer);
static gboolean configure_it(GtkWidget *, GdkEventConfigure *, gpointer);
static gboolean draw_it(GtkWidget *, cairo_t *, gpointer);


int main(int argc, char **argv)
{
    GtkApplication *app_p;
    m_data_struct my_data;
    int status;

    my_data.scaling_factor = 1.0/11.0;
    my_data.final_surface_p = NULL;

    app_p = gtk_application_new("calc.foil", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app_p, "activate", G_CALLBACK(activate), &my_data);
    status = g_application_run(G_APPLICATION(app_p), 0, NULL);
    g_object_unref(app_p);
}


static void activate(GtkApplication *app_p, gpointer g_data_p)
{
    GtkWidget *frame_p, *notebook_p, *grid0_p, *grid1_p, *drawing_area_p;
    m_data_struct *my_data_p;
    cairo_t *cr_p;

    my_data_p = (m_data_struct *)g_data_p;

    my_data_p->window_p = gtk_application_window_new(app_p);
    gtk_window_set_title(GTK_WINDOW(my_data_p->window_p), "Fot Calculation");

    gtk_container_set_border_width(GTK_CONTAINER(my_data_p->window_p), 8);

    notebook_p = gtk_notebook_new();
    gtk_container_add(GTK_CONTAINER(my_data_p->window_p), notebook_p);

    grid0_p = gtk_grid_new();
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook_p), grid0_p, 
                 gtk_label_new("First Tab"));

    grid1_p = gtk_grid_new();
    gtk_grid_attach(GTK_GRID(grid0_p), grid1_p, 2, 2, 2, 50);

    frame_p = gtk_frame_new("Rectangle");
    drawing_area_p = gtk_drawing_area_new();
    gtk_widget_set_size_request(frame_p, 300, 300);
    g_signal_connect(drawing_area_p, "configure-event",
             G_CALLBACK(configure_it), g_data_p);
    g_signal_connect(drawing_area_p, "draw", G_CALLBACK(draw_it), g_data_p);
    g_signal_connect(drawing_area_p, "scroll-event", G_CALLBACK(zoom_it),
             g_data_p);
    gtk_widget_set_events(drawing_area_p,
              gtk_widget_get_events(drawing_area_p)
              | GDK_SCROLL_MASK);

    gtk_container_add(GTK_CONTAINER(frame_p), drawing_area_p);
    gtk_grid_attach(GTK_GRID(grid1_p), frame_p, 1, 0, 1, 2);
    my_data_p->circle_surface_p 
    = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 3000, 3000);
    cr_p = cairo_create(my_data_p->circle_surface_p);
    cairo_set_line_width(cr_p, 10);
    cairo_rectangle(cr_p, 100, 100, 2900, 2900);
    cairo_set_source_rgb(cr_p, 0, 0, 0);
    cairo_stroke(cr_p);

    gtk_widget_show_all(my_data_p->window_p);
}


static gboolean zoom_it(GtkWidget *widget_p,
            GdkEvent *event_p,
            gpointer g_data_p)
{
    if (((GdkEventScroll *)event_p)->direction == GDK_SCROLL_UP)
    {
    ((m_data_struct *)g_data_p)->scaling_factor *= ZOOMING_STEP;

    configure_it(widget_p, (GdkEventConfigure *)event_p, g_data_p);
    gtk_widget_queue_draw(widget_p);
    }
    if (((GdkEventScroll *)event_p)->direction == GDK_SCROLL_DOWN)
    {
    ((m_data_struct *)g_data_p)->scaling_factor /= ZOOMING_STEP;

    configure_it(widget_p, (GdkEventConfigure *)event_p, g_data_p);
    gtk_widget_queue_draw(widget_p);
    }

    return TRUE;
}


static gboolean configure_it(GtkWidget *widget_p,
                 GdkEventConfigure *event_p,
                 gpointer g_data_p)
{
    cairo_t *cr_p;
    m_data_struct * my_data_p;

    my_data_p = (m_data_struct *)g_data_p;

    if (my_data_p->final_surface_p)
    cairo_surface_destroy(my_data_p->final_surface_p);
    my_data_p->final_surface_p
    = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300);

    cr_p = cairo_create(my_data_p->final_surface_p);
    cairo_scale(cr_p, my_data_p->scaling_factor, my_data_p->scaling_factor);
    cairo_set_source_surface(cr_p, my_data_p->circle_surface_p, 0, 0);
    cairo_paint(cr_p);
    cairo_destroy(cr_p);

    return TRUE;
}


static gboolean draw_it(GtkWidget *widget_p,
            cairo_t *cr_p,
            gpointer g_data_p)
{
    cairo_set_source_surface(cr_p, ((m_data_struct *)g_data_p)->final_surface_p,
                 0, 0);
    cairo_paint(cr_p);

    return FALSE;
}
...