Как добавить GtkWidget в пользовательский?

#c #gtk #gtk3 #custom-widgets

#c #gtk #gtk3 #пользовательские виджеты

Вопрос:

Я создал пользовательский виджет GTK, и мне нужно добавить к нему кнопку GTK, чтобы наследовать его сигналы в пользовательском. Пользовательский виджет представляет собой временную шкалу, поэтому я решил использовать кнопки GTK, чтобы не путаться с координатами мыши. Когда пользователь захочет переместить изображение, представленное кнопкой, или просто продлить его задержку на самой временной шкале, из виджета кнопки будут поступать сигналы, и моя жизнь станет намного проще.

Кнопка, конечно, не отображается на временной шкале. это моя проблема. Я знаю, что мне нужно поместить кнопку внутри контейнера, но как это сделать в функции рисования? Кто-нибудь знает, как это сделать? Я погуглил и посмотрел здесь, но безуспешно.

Это функция рисования пользовательского виджета:

 static gboolean img_timeline_draw(GtkWidget *da, cairo_t *cr)
{
  GtkWidget *button; 
  ImgTimelinePrivate *priv = img_timeline_get_instance_private((ImgTimeline*)da);
  gint width = gtk_widget_get_allocated_width(da);
  
  cairo_translate (cr, 0 , 12);

  img_timeline_draw_time_ticks(da, cr, width);
  
  //Video timeline
  cairo_translate (cr, 0 , 20);
  cairo_set_source_rgba(cr, priv->video_background[0], priv->video_background[1], priv->video_background[2], priv->video_background[3]);
  cairo_set_line_width(cr, 1);
  cairo_rectangle(cr, 0,10, width - 2, 59);
  cairo_fill(cr);
  //separator
  cairo_set_source_rgb(cr, 1, 1, 1);
  cairo_rectangle(cr, 0,69, width - 2, 3);
  cairo_fill(cr);
  //Audio timeline
  cairo_set_source_rgba(cr, priv->audio_background[0], priv->audio_background[1], priv->audio_background[2], priv->audio_background[3]);
  cairo_rectangle(cr, 0,72, width - 2, 59);
  cairo_fill(cr);

  button = gtk_button_new_with_label("I'm invisible...");
  gtk_widget_set_realized(button, TRUE);
  gtk_widget_show(button);
  return FALSE;
}
 

И это основной:

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

  GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "Imagination timeline widget");
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 800, 200);
  g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

  GtkWidget *timeline = img_timeline_new();
  g_object_set(timeline, "total_time",        300, NULL);
  g_object_set(timeline, "video_background", "#0084ff", NULL);
  g_object_set(timeline, "audio_background", "#0084ff", NULL);

  gtk_widget_add_events( timeline, GDK_BUTTON1_MOTION_MASK
                         | GDK_POINTER_MOTION_HINT_MASK
                         | GDK_BUTTON_PRESS_MASK
                         | GDK_BUTTON_RELEASE_MASK
                         | GDK_SCROLL_MASK
                         | GDK_KEY_PRESS_MASK );

  GtkWidget *scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL);
  GtkWidget *viewport = gtk_viewport_new(NULL,NULL);
  g_signal_connect( G_OBJECT(timeline), "scroll-event", G_CALLBACK(img_timeline_scroll), scrolledwindow1);

  gtk_widget_set_hexpand(viewport, TRUE);
  gtk_widget_set_vexpand(viewport, TRUE);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
  
  gtk_container_add (GTK_CONTAINER(viewport), timeline);
  gtk_container_add (GTK_CONTAINER(scrolledwindow1), viewport);
  gtk_container_add (GTK_CONTAINER (window), scrolledwindow1);
  gtk_widget_show_all(window);

  gtk_main();
  return 0;
}
 

Ответ №1:

Хорошо, решение состояло в том, чтобы создать подкласс GtkLayout вместо GtkDrawingArea и использовать gtk_container_propagate_draw() в функции рисования пользовательского виджета!