为了账号安全,请及时绑定邮箱和手机立即绑定

C指针原理(26)-gtk

标签:
C++


下面演示了如何在窗口中增加一个按钮,示例代码均有注释 

#include <gtk/gtk.h>

static void print_hello (GtkWidget *widget,gpointer data)

{

//这是一个回调函数,这个data表示传给回调函数的参数。

  g_print ("你好,世界\n");

}

static gboolean on_delete_event (GtkWidget *widget,GdkEvent *event,gpointer data)

{

//如果返回FALSE在delete_event信号处理中,GTK将发送destroy信号,否则不会,这样窗口就不会关闭。

  g_print ("delete event occurred\n");

  return TRUE;

}

int main (int argc,char *argv[])

{

        GtkWidget *window;

    GtkWidget *button;

    //初始化gtk应用程序

    gtk_init (&argc, &argv);

    //创造新的窗口,设置它的标题

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "你好");

    //将delete_event信号绑定在on_delte_devent回调函数上,传递的参数为NULL

            g_signal_connect (window, "delete-event", G_CALLBACK (on_delete_event), NULL);

    //将destroy信号绑定在gtk_main_quit回调函数上,传递的参数为NULL

            g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

    //设置窗口的边框宽度

            gtk_container_set_border_width (GTK_CONTAINER (window), 10);

    //创建一个新的标签 

         button = gtk_button_new_with_label ("Hello World");

     //处理按钮的clicked信号

    g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);

            //g_signal_connect_swapped将clicked信号连接到window窗口的gtk_widget_destroy事件中。

            g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);

            //将按钮加入到容器中

            gtk_container_add (GTK_CONTAINER (window), button);

    //显示这个按钮

            gtk_widget_show (button);

           //显示窗口

    gtk_widget_show (window);

    //开始GTK的主循环

            gtk_main ();

            return 0;

}

在XMANGER下用VIM编写好后,编译运行

#include <gtk/gtk.h>

/* Surface to store current scribbles */

static cairo_surface_t *surface = NULL;

static void

clear_surface (void)

{

  cairo_t *cr;

  cr = cairo_create (surface);

  cairo_set_source_rgb (cr, 1, 1, 1);

  cairo_paint (cr);

  cairo_destroy (cr);

}

/* Create a new surface of the appropriate size to store our scribbles */

static gboolean

configure_event_cb (GtkWidget         *widget,

                    GdkEventConfigure *event,

                    gpointer           data)

{

  if (surface)

    cairo_surface_destroy (surface);

  surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),

                                               CAIRO_CONTENT_COLOR,

                                               gtk_widget_get_allocated_width (widget),

                                               gtk_widget_get_allocated_height (widget));

  /* Initialize the surface to white */

  clear_surface ();

  /* We've handled the configure event, no need for further processing. */

  return TRUE;

}

/* Redraw the screen from the surface. Note that the ::draw

 * signal receives a ready-to-be-used cairo_t that is already

 * clipped to only draw the exposed areas of the widget

 */

static gboolean

draw_cb (GtkWidget *widget,

         cairo_t   *cr,

         gpointer   data)

{

  cairo_set_source_surface (cr, surface, 0, 0);

  cairo_paint (cr);

  return FALSE;

}

/* Draw a rectangle on the surface at the given position */

static void

draw_brush (GtkWidget *widget,

            gdouble    x,

            gdouble    y)

{

  cairo_t *cr;

  /* Paint to the surface, where we store our state */

  cr = cairo_create (surface);

  cairo_rectangle (cr, x - 3, y - 3, 6, 6);

  cairo_fill (cr);

  cairo_destroy (cr);

  /* Now invalidate the affected region of the drawing area. */

  gtk_widget_queue_draw_area (widget, x - 3, y - 3, 6, 6);

}

/* Handle button press events by either drawing a rectangle

 * or clearing the surface, depending on which button was pressed.

 * The ::button-press signal handler receives a GdkEventButton

 * struct which contains this information.

 */

static gboolean

button_press_event_cb (GtkWidget      *widget,

                       GdkEventButton *event,

                       gpointer        data)

{

  /* paranoia check, in case we haven't gotten a configure event */

  if (surface == NULL)

    return FALSE;

  if (event->button == 1)

    {

      draw_brush (widget, event->x, event->y);

    }

  else if (event->button == 3)

    {

      clear_surface ();

      gtk_widget_queue_draw (widget);

    }

  /* We've handled the event, stop processing */

  return TRUE;

}

/* Handle motion events by continuing to draw if button 1 is

 * still held down. The ::motion-notify signal handler receives

 * a GdkEventMotion struct which contains this information.

 */

static gboolean

motion_notify_event_cb (GtkWidget      *widget,

                        GdkEventMotion *event,

                        gpointer        data)

{

  int x, y;

  GdkModifierType state;

  /* paranoia check, in case we haven't gotten a configure event */

  if (surface == NULL)

    return FALSE;

  /* This call is very important; it requests the next motion event.

   * If you don't call gdk_window_get_pointer() you'll only get

   * a single motion event. The reason is that we specified

   * GDK_POINTER_MOTION_HINT_MASK to gtk_widget_set_events().

   * If we hadn't specified that, we could just use event->x, event->y

   * as the pointer location. But we'd also get deluged in events.

   * By requesting the next event as we handle the current one,

   * we avoid getting a huge number of events faster than we

   * can cope.

   */

  gdk_window_get_pointer (event->window, &x, &y, &state);

  if (state & GDK_BUTTON1_MASK)

    draw_brush (widget, x, y);

  /* We've handled it, stop processing */

  return TRUE;

}

static void

close_window (void)

{

  if (surface)

    cairo_surface_destroy (surface);

  gtk_main_quit ();

}

int

main (int   argc,

      char *argv[])

{

  GtkWidget *window;

  GtkWidget *frame;

  GtkWidget *da;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");

  g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);

  gtk_container_set_border_width (GTK_CONTAINER (window), 8);

  frame = gtk_frame_new (NULL);

  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);

  gtk_container_add (GTK_CONTAINER (window), frame);

  da = gtk_drawing_area_new ();

  /* set a minimum size */

  gtk_widget_set_size_request (da, 100, 100);

  gtk_container_add (GTK_CONTAINER (frame), da);

  /* Signals used to handle the backing surface */

  g_signal_connect (da, "draw",

                    G_CALLBACK (draw_cb), NULL);

  g_signal_connect (da,"configure-event",

                    G_CALLBACK (configure_event_cb), NULL);

  /* Event signals */

  g_signal_connect (da, "motion-notify-event",

                    G_CALLBACK (motion_notify_event_cb), NULL);

  g_signal_connect (da, "button-press-event",

                    G_CALLBACK (button_press_event_cb), NULL);

  /* Ask to receive events the drawing area doesn't normally

   * subscribe to. In particular, we need to ask for the

   * button press and motion notify events that want to handle.

   */

  gtk_widget_set_events (da, gtk_widget_get_events (da)

                             | GDK_BUTTON_PRESS_MASK

                             | GDK_POINTER_MOTION_MASK

                             | GDK_POINTER_MOTION_HINT_MASK);

  gtk_widget_show_all (window);

  gtk_main ();

  return 0;

}

©著作权归作者所有:来自51CTO博客作者myhaspl的原创作品,如需转载,请注明出处,否则将追究法律责任


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消