• GTK入门


    环境准备

    官网下载 GTK 源码包,因为本机 GLib 版本不够,下载一个非最新版的 GTK3.8.0 先学习用

    直接阅读 "/gtk+-3.8.0/docs/reference/gtk/html/gtk-building.html" 进行操作

    安装完毕,gtk3-demo 出来 gtk 的样例界面即安装搞定

    实例学习

    编译命令和编译脚本

    编译参数包括 pkg-config --libs --cflags gtk+-3.0

    为了方便,用脚本管理起来

    build.sh

    #!/bin/bash
    if [ $# -lt 1 ]; then
        echo "usage: $0 [xxxx.c]"
        exit
    fi
     
    gcc -o $1_out $1 `pkg-config --libs --cflags gtk+-3.0`
    

    一个简单的HelloWorld按钮

    01_simple_button.c

    #include <gtk/gtk.h>
    
    // 回调函数1
    void hello( GtkWidget *widget, GdkEvent *event, gpointer data )
    {
        g_print("Hello World
    ");
    }
    
    // 回调函数2
    void destroy( GtkWidget *widget, gpointer data )
    {
        gtk_main_quit();
    }
    
    gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
    {
        /**
         * 如果 "delete_event" 信号处理函数
         * 返回 FALSE,GTK 会发出 "destroy" 信号
         * 返回 TRUE,你不希望关闭窗口
         * 当希望弹出 "你确定要退出吗?" 对话框时可以用到
         */
        g_print("delete event occurred
    ");
    
        return FALSE;
    }
    
    int main( int argc, char *argv[] )
    {
        // GtkWidget 是构件的存储类型
        GtkWidget *window;
        GtkWidget *button;
    
        /**
         * gtk_init 函数在所有的 GTK 程序都要调用
         * 参数由命令行中解析出并填充进来
         */
        gtk_init( &argc, &argv );
    
        window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    
        /**
         * 当窗口收到 "delete_event" 信号(该信号由窗口管理器发出,
         * 通常是"关闭"选项或是标题栏上的关闭按钮发出的)
         * 我们让其调用在前面定义的 delete_event 函数
         * 传给回调函数的 data 参数值是 NULL,它会被回调函数忽略
         */
        g_signal_connect( G_OBJECT( window ), "delete_event",
            G_CALLBACK( delete_event ), NULL );
    
        /**
         * 连接 "destroy" 事件到一个信号处理函数,对该窗口调用
         * gtk_widget_destroy 函数或在 "delete_event" 回调函数
         * 中返回 FALSE 值都会触发该事件
         */
        g_signal_connect( G_OBJECT( window ), "destroy",
            G_CALLBACK( destroy ), NULL );
    
        // 设置窗口边框的宽度
        gtk_container_set_border_width ( GTK_CONTAINER(window), 10 );
        // 创建一个标签为 Hello World 的新按钮
        button = gtk_button_new_with_label( "Hello World" );
    
        // 当按钮触发 "clicked" 事件时,会调用回调函数 hello
        g_signal_connect( G_OBJECT( button ), "clicked",
            G_CALLBACK( hello ), "1" );
    
        // 当按钮触发 "clicked" 事件时,调用 gtk_widget_destroy(window)
        // 来关闭窗口,"destroy" 信号会从这里或从窗口管理器发出
        // g_signal_connect_swapped (G_OBJECT (button), "clicked",
        //     G_CALLBACK (gtk_widget_destroy),window);
        
        // 把按钮放入窗口(一个gtk容器)中
        gtk_container_add ( GTK_CONTAINER( window), button );
        
        // 显示新创建的按钮和窗口
        gtk_widget_show( button );
        gtk_widget_show( window );
    
        // 程序运行停在这里等待事件的发生(如键盘事件/鼠标事件)
        gtk_main();
    
        return 0;
    }
    

    两个按钮

    02_two_buttons.c

    #include <gtk/gtk.h>
    
    // 改进回调函数,传递到该函数的数据将打印到标准输出中(stdout)
    void callback( GtkWidget *widget, gpointer data )
    {
        g_print( "%s", (gchar *) data );
    }
    
    // 回调函数2
    gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
    {
        gtk_main_quit();
        return FALSE;
    }
    
    int main( int argc, char *argv[] )
    {
        GtkWidget *window;
        GtkWidget *button;
        GtkWidget *box1;
    
        gtk_init( &argc, &argv );
        window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
        
        // 设置窗口标题
        gtk_window_set_title( GTK_WINDOW( window ), "Hello Buttons!" );
    
        g_signal_connect( G_OBJECT( window ), "delete_event",
            G_CALLBACK( delete_event ), NULL );
    
        gtk_container_set_border_width( GTK_CONTAINER( window ), 20 );
    
        // 创建一个组装盒,组装盒非可见,它仅被作为排列构件的工具
        box1 = gtk_hbox_new( FALSE, 1 );
        // 把组装盒放入主窗口中
        gtk_container_add ( GTK_CONTAINER( window ), box1 );
        
        button = gtk_button_new_with_label( "Hello" );
        g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "hello");
        
        // 代替 gtk_container_add, 把按钮放入组装盒中, 组装盒已经放入窗口中了
        gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 );
        gtk_widget_show( button );
    
        button = gtk_button_new_with_label( "World" );
        g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "World");
        gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 );
        gtk_widget_show( button );
    
        button = gtk_button_new_with_label( "!" );
        g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "!");
        gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 );
        gtk_widget_show( button );
    
        gtk_widget_show( box1 );
        gtk_widget_show( window );
        
        gtk_main();
    
        return 0;
    }
    

    一图片和一按钮

    03_image_and_button.c

    #include "gtk/gtk.h"
    
    int main( int argc, char *argv[] )
    {
        GtkWidget* window;
        GtkWidget* vbox;
        GtkWidget* image;
        GtkWidget* button;
      
        gtk_init( &argc, &argv );
      
        window = gtk_window_new( GTK_WINDOW_POPUP );
        gtk_window_set_title( GTK_WINDOW(window), "Splash窗口" );
        g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL );
        
        // 设置窗口处于屏幕中央
        gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_CENTER );
        // gtk_container_set_border_width( GTK_CONTAINER(window), 20 );
      
        vbox = gtk_vbox_new(FALSE, 0);
        gtk_container_add( GTK_CONTAINER(window), vbox );
        
        image = gtk_image_new_from_file("gnome-desktop.png");
        gtk_box_pack_start( GTK_BOX(vbox), image, FALSE, FALSE, 0 );
      
        button = gtk_button_new_with_label( "Splash窗口" );
        g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_main_quit ), NULL );
      
        gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
        gtk_widget_show_all( window );
      
        gtk_main();
    
        return FALSE;
    }
    

    可前进后退的提示窗口

    04_notify_window.c

    #include <gtk/gtk.h>
    
    // XPM格式图像数据
    static char * book_open_xml[] = {
    	"16 16 4 1",
    	" c None s None",
    	". c black",
    	"X c #808080",
    	"o c white",
    	" ",
    	" .. ",
    	" .Xo. ... ",
    	" .Xoo. ..oo. ",
    	" .Xooo.Xooo... ",
    	" .Xooo.oooo.X. ",
    	" .Xooo.Xooo.X. ",
    	" .Xooo.oooo.X. ",
    	" .Xooo.Xooo.X. ",
    	" .Xooo.oooo.X. ",
    	" .Xoo.Xoo..X. ",
    	" .Xo.o..ooX. ",
    	" .X..XXXXX. ",
    	" ..X....... ",
    	" .. ",
    	" "
    };
    
    // 自定义提示
    static gchar *info[5] = {
       "此软件用于测试每日提示功能的实现,如果你发现问题请及时回复。",
       "我们的目的是把GTK+2.0的大多数功能奉献给每一位自由软件爱好者和开发者。",
       "每一位Linux的支持者都会让我们增加一分信心,Linux最终仍是台式计算机操作系统。",
       "计算机软件技术是一种科学技术,它和人类历史上其他的科学技术一样,是允许每一人自由使用的。",
       "当前你测试完此程序后,请设法把它附加到你创作的软件当中去,这是你成功的第一步。"
    };
    
    static GtkWidget *window;			// 主窗口
    static GtkWidget *frame;			// 框架
    static GtkWidget *pre_button;		// 上一提示按钮
    static GtkWidget *next_button;		// 下一提示按钮
    static GtkWidget *label;			// 提示信息内容标签
    static GtkWidget *title;			// 框架标题
    
    gint current_info = 0;				// 当前提示信息计数
    
    // 创建框架控件标题
    GtkWidget* create_title( GtkWidget *data )
    {
    	GtkWindow *title;
    	GtkWindow *hbox;
    	GtkWindow *image;
    	GtkWindow *label;
    	GtkWindow *pixmap;
    	GtkWindow *mask;
    	GdkWindow *window;
    
    	pixmap = gdk_pixbuf_new_from_xpm_data ( book_open_xml );
    	image = gtk_image_new_from_pixbuf( pixmap );
    	label = gtk_label_new( "新的标题" );
    	hbox = gtk_hbox_new( FALSE, 0 );
    
    	gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 2 );
    	gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 2 );
    
    	return hbox;
    }
    
    GtkWidget* create_button( gchar* stockid, gchar* title )
    {
    	GtkWidget *button;
    	GtkWidget *image;
    	GtkWidget *label;
    	GtkWidget *hbox;
    
    	image = gtk_image_new_from_stock( stockid, GTK_ICON_SIZE_MENU );
    	label = gtk_label_new( title );
    	hbox = gtk_hbox_new( FALSE, 0 );
    	gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 3 );
    	gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 3 );
    	
    	button = gtk_button_new();
    	gtk_container_add( GTK_CONTAINER(button), hbox );
    	
    	return button;
    }
    
    // 上一提示
    void pre_info( GtkButton *button, gpointer data )
    {
    	gint i;
    	i = current_info - 1;
    	if (i == -1 ) return;
    	if (i == 0  ) gtk_widget_set_sensitive( pre_button, FALSE );
    	current_info = i;
    	gtk_widget_set_sensitive( next_button, TRUE );
    	gtk_label_set_text( GTK_LABEL( label ), info[current_info] ); 
    }
    
    // 下一提示
    void next_info( GtkButton *button, gpointer data )
    {
    	gint i;
    	i = current_info + 1;
    	if (i == 5 ) return;
    	if (i == 4 ) gtk_widget_set_sensitive( next_button, FALSE );
    	current_info = i;
    	gtk_widget_set_sensitive( pre_button, TRUE );
    	gtk_label_set_text( GTK_LABEL( label ), info[current_info] ); 
    }
    
    int main( int argc, char* argv[] )
    {
    	GtkWidget *hbox;
    	GtkWidget *vbox;
    	GtkWidget *bbox;
    	GtkWidget *button;
    	GtkWidget *image;
    	GtkWidget *title;
    
    	gtk_init( &argc, &argv );
    	window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    	g_signal_connect( G_OBJECT( window ), "delete_event", G_CALLBACK( gtk_main_quit ), NULL );
    
    	gtk_window_set_title( GTK_WINDOW( window ), "每日提示" );
    	gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_CENTER );
    	gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
    	gtk_widget_realize( window );
    
    	vbox = gtk_vbox_new( FALSE, 0 );
    	gtk_container_add( GTK_CONTAINER( window ), vbox );
    	
    	hbox = gtk_hbox_new( FALSE, 0 );
    	gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 5 );
    	
    	image = gtk_image_new_from_file( "gnome-desktop.png" );
    	gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 5 );
    	
    	frame = gtk_frame_new( NULL );
    	title = create_title( window );
    	gtk_frame_set_label_widget( GTK_FRAME( frame ), title );
    	gtk_box_pack_start( GTK_BOX( hbox ), frame, TRUE, TRUE, 5 );
    
    	label = gtk_label_new( NULL );
    	gtk_label_set_text( GTK_LABEL( label ), info[0] );
    	gtk_label_set_line_wrap( GTK_LABEL( label ), TRUE );
    	gtk_container_add( GTK_CONTAINER( frame ), label );
    
    	bbox = gtk_hbutton_box_new();
    	gtk_button_box_set_layout( GTK_BUTTON_BOX( bbox ), GTK_BUTTONBOX_END );
    	gtk_box_pack_start( GTK_BOX( vbox ), bbox, FALSE, FALSE, 5 );
    
    	button = gtk_check_button_new_with_label( "每次启动时显示" );
    	gtk_box_pack_start( GTK_BOX( bbox ), button, FALSE, FALSE, 5 );
    
    	pre_button = create_button( GTK_STOCK_GO_BACK, "上一提示" );
    	gtk_widget_set_sensitive ( pre_button, FALSE );
    	g_signal_connect( G_OBJECT( pre_button ), "clicked", G_CALLBACK( pre_info ), NULL );
    	gtk_box_pack_start( GTK_BOX( bbox ), pre_button, FALSE, FALSE, 5 );
    	
    	next_button = create_button( GTK_STOCK_GO_FORWARD, "下一提示" );
    	g_signal_connect( G_OBJECT( next_button ), "clicked", G_CALLBACK( next_info ), NULL );
    	gtk_box_pack_start( GTK_BOX( bbox ), next_button, FALSE, FALSE, 5 );
    	
    	button = gtk_button_new_from_stock( GTK_STOCK_OK );
    	g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_main_quit ), NULL );
    	gtk_box_pack_start( GTK_BOX( bbox ), button, FALSE, FALSE, 5 );
    
    	gtk_widget_show_all( window );
    	gtk_main();
    
    	return FALSE;
    }
    

    ... 后面有空继续更新

    总结

    gtk+ 现有资料已经很少了, 属于淘汰型技术了, 勿深究.

  • 相关阅读:
    蓝桥杯 2014本科C++ B组 六角填数 枚举排列
    蓝桥杯 2014本科C++ B组 地宫取宝 DFS+记忆化搜索
    埃及分数 IDA*
    优先队列详解(转载)
    HDU 1242 Rescue BFS+优先队列
    HDU 1627 Krypton Factor
    2018中国机器人大赛服务机器人专项赛赛后总结
    OpenMP使用体验报告(概述)
    写在归程路上——2018ROBOCUP机器人世界杯中国赛
    ROS编译工作区缺少cv_bridge的问题解决
  • 原文地址:https://www.cnblogs.com/hencins/p/12204099.html
Copyright © 2020-2023  润新知