C语言写一个GTK的二维码图形界面生成器-阿里云开发者社区

开发者社区> geek2pm> 正文

C语言写一个GTK的二维码图形界面生成器

简介:
+关注继续查看

最终效果如下:
demo

其实这个程序并不能自己生成二维码,它只是调用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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Docker服务器的图形显示方案
欢迎关注大数据和人工智能技术文章发布的微信公众号:清研学堂,在这里你可以学到夜白(作者笔名)精心整理的笔记,让我们每天进步一点点,让优秀成为一种习惯! 问题描述:一般docker实操时都是作为服务器,以字符方式交互,非常不方便。
1445 0
c语言运算符号详细说明
C语言中具有右结合性的运算符包括所有单目运算符以及赋值运算符(=)和条件运算符。其它都是左结合性。 判断表达式计算顺序时,先按优先级高的先计算,优先级低的后计算,当优先级相同时再按结合性,或从左至右顺序计算,或从右至左顺序计算。
888 0
DL之RNN:人工智能为你写代码——基于TF利用RNN算法实现生成编程语言代码(C++语言)、训练&测试过程全记录(二)
DL之RNN:人工智能为你写代码——基于TF利用RNN算法实现生成编程语言代码(C++语言)、训练&测试过程全记录
29 0
带你读《C指针原理揭秘:基于底层实现机制》之一:C语言概述
本书从底层实现机制进行解析,同时配合C/C++编程技巧以及某些指针运用技巧,讲解如何提高程序效能,如何避免滥用指针,从C语言编程的角度讲解C指针,力图使读者学会运用C指针进行开发,并能进一步灵活将指针运用在精巧的算法上,构造更复杂的软件系统。
1448 0
用VC编译lua源码,生成lua语言的解释器和编译器
用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编译源码,我们需要编译: 一个静态库 一个动态库 一个lua语言解释器 一个lua编译器 ...
806 0
C语言中使用大括号与给函数命名的正确方法(转载)
使用大括号的正确方法: 在C中,使用大括号的方法无所谓对还是错——只要每个开括号后都有一个闭括号,你的程序中就不再会出现与大括号有关的问题。
985 0
带你读《C指针原理揭秘:基于底层实现机制》之二:C语言快速入门
本书从底层实现机制进行解析,同时配合C/C++编程技巧以及某些指针运用技巧,讲解如何提高程序效能,如何避免滥用指针,从C语言编程的角度讲解C指针,力图使读者学会运用C指针进行开发,并能进一步灵活将指针运用在精巧的算法上,构造更复杂的软件系统。
1144 0
+关注
1
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载