天天看點

C語言寫一個GTK的二維碼圖形界面生成器

最終效果如下:

C語言寫一個GTK的二維碼圖形界面生成器

其實這個程式并不能自己生成二維碼,它隻是調用qrencode來生成二維碼,并顯示出來。

qrencode 需要執行以下指令安裝:

sudo apt install qrencode           

而生成二維碼很簡單,隻需要一個指令:

qrencode -l L -v 1 -s 11 -o output.png xxx           

上面的xxx就是需要生成二維碼的内容。

是以,這個程式僅僅是做了一個圖形界面的殼子,取得使用者輸入的内容,背地裡調用qrencode生成二維碼,然後再顯示到GUI裡。

是以,整體流程如下:

添加描述

當按鈕按動後,執行兩個步驟:

1、讀取輸入框的内容,通過qrencode生成二維碼圖檔。

char *get_text(){
    return gtk_entry_get_text (GTK_ENTRY(g_entry));
}           
void call_qrencode(char *text){
    char cmd[500];
    strcpy (cmd,"qrencode -l L -v 1 -s 11 -o output.png '");
    strcat (cmd,text);
    strcat (cmd,"'");
    system(cmd);
}           

2、讀取生成的二維碼圖檔,在GTK的image控件上顯示。

gboolean load_qrencode_img(){
    src_pixbuf = gdk_pixbuf_new_from_file("output.png", NULL); 
    dest_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, 300, 300, GDK_INTERP_HYPER);
    gtk_image_set_from_pixbuf (GTK_IMAGE(g_image),dest_pixbuf);
    return FALSE;
}           

由于生成圖檔需要時間,是以在第二個步驟之前,要執行一個延時。但這個延時不是sleep,如果使用sleep,那麼就無法實作動圖的特效。動圖是為了避免延時産生的空白被使用者誤認為卡頓。

是以這裡的延時,使用的是一個線程定時器,但為了避免定時,是以定時的函數中,傳回一個FALSE,導緻定時隻執行一次便失效,進而實作了延時。

最後,在按鈕上增加一個信号:

g_signal_connect(g_btn, "clicked",G_CALLBACK(make), NULL);           

相應地,make函數則十分簡單:

void make(){
    call_qrencode(get_text());
    g_timeout_add(1000, (GSourceFunc)load_qrencode_img, NULL);
}           

隻要這兩個步驟,在功能上已經可以了。

但是,由于調用qrencode後有一個延時,會導緻使用者主觀上誤認為卡頓,使用者體驗不好。是以,可以在延時的空隙中,增加一個動畫,就像網頁沒打開時出一個loading的動畫一樣。

主要代碼如下:

void load_loading_img(){
    GError *error = NULL;
    anim_pixbuf = gdk_pixbuf_animation_new_from_file("loading.gif", &error);
    if(error!=NULL){
       printf("Error: %s\n", error->message);
       g_error_free(error);
       error = NULL;
    }
    gtk_image_set_from_animation (GTK_IMAGE(g_image),anim_pixbuf);  
}           

這樣,make的函數則如下:

void make(){
    call_qrencode(get_text());
    load_loading_img();
    g_timeout_add(1000, (GSourceFunc)load_qrencode_img, NULL);
}           

全部代碼如下:

#include <gtk/gtk.h>
#include <unistd.h>
GtkWidget *window;
GtkWidget *fixed;
GtkWidget *g_image;
GtkWidget *g_btn;
GtkWidget *g_entry;
GdkPixbufAnimation* anim_pixbuf;
const GdkPixbuf *src_pixbuf;
GdkPixbuf *dest_pixbuf;
 
void destroy(GtkWidget *widget,gpointer data){
    gtk_main_quit();
}

void load_default_img()
{
    src_pixbuf = gdk_pixbuf_new_from_file("img.png", NULL); 
    dest_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, 300, 300, GDK_INTERP_HYPER);
    gtk_image_set_from_pixbuf (GTK_IMAGE(g_image),dest_pixbuf);
}

char *get_text(){
    return gtk_entry_get_text (GTK_ENTRY(g_entry));
}

void call_qrencode(char *text){
    char cmd[500];
    strcpy (cmd,"qrencode -l L -v 1 -s 11 -o output.png '");
    strcat (cmd,text);
    strcat (cmd,"'");
    system(cmd);
}

void load_loading_img(){
    GError *error = NULL;
    anim_pixbuf = gdk_pixbuf_animation_new_from_file("loading.gif", &error);
    if(error!=NULL){
       printf("Error: %s\n", error->message);
       g_error_free(error);
       error = NULL;
    }
    gtk_image_set_from_animation (GTK_IMAGE(g_image),anim_pixbuf);  
}

gboolean load_qrencode_img(){
    src_pixbuf = gdk_pixbuf_new_from_file("output.png", NULL); 
    dest_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, 300, 300, GDK_INTERP_HYPER);
    gtk_image_set_from_pixbuf (GTK_IMAGE(g_image),dest_pixbuf);
    return FALSE;
}

void make(){
    call_qrencode(get_text());
    load_loading_img();
    g_timeout_add(1000, (GSourceFunc)load_qrencode_img, NULL);
}

int main(int argc,char *argv[]){
    gtk_init (&argc, &argv);
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    gtk_window_set_default_size(GTK_WINDOW(window),320,380);
    gtk_window_set_resizable (GTK_WINDOW(window),FALSE);
    g_signal_connect(window, "destroy",G_CALLBACK (destroy), NULL);
    gtk_window_set_title(GTK_WINDOW(window),"qrencode GUI");
    gtk_window_set_keep_above(GTK_WINDOW (window), TRUE);
    fixed = gtk_fixed_new ();
    g_btn = gtk_button_new_with_mnemonic ("make");
    g_signal_connect(g_btn, "clicked",G_CALLBACK(make), NULL);
    gtk_widget_set_size_request(g_btn,80,50);
    g_entry = gtk_entry_new ();
    gtk_widget_set_size_request(g_entry,210,50);
    g_image = gtk_image_new ();
    gtk_widget_set_size_request(GTK_WIDGET(g_image),300,300);
    gtk_fixed_put (GTK_FIXED(fixed),g_image,0,0);
    gtk_fixed_put (GTK_FIXED(fixed),g_entry,0,320);
    gtk_fixed_put (GTK_FIXED(fixed),g_btn,220,320);
    gtk_container_add (GTK_CONTAINER (window), fixed);
    gtk_widget_show_all (window);
    gtk_widget_set_opacity (GTK_WIDGET (window), 0.9);
    load_default_img();
    gtk_main ();
    return 0;
}           

使用如下指令即可生成可執行檔案:

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

最後,本代碼位于

https://github.com/geek2pm/gtk_qrencode_gui

繼續閱讀