最终效果如下:
其实这个程序并不能自己生成二维码,它只是调用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`