第一个Gtk写的实用小程序《健康提示小助手》

高手免进!!!

今天下午考完一门科目,终于有时间学习以下gtk了! Devhelp很不错,不但有api手册,还有tutorial和示例源代码,越来越喜欢泡在help里了。。。gtk的界面设计还是很先进的,win上没有的盒子模型和组合表。我早就幻想过能够像设计网页那样方便地设计应用程序的界面,而gtk很容易实现这个想法。创建一个table,你就可以让你的控件以任意形式放置在任意位置的一个或多个单元格中。个人觉得,什么时候能够用一个css文件来给窗体装裱样式就更方便了。

心不在焉的看了1个多小时手册,然后写了1个小时代码(有点笨),结果如下:

配置界面:

 

源代码:

  1. #include <stdlib.h>  
  2. #include <gtk/gtk.h>  
  3. #include <time.h>  
  4. #include <libnotify/notify.h>  
  5. #include <stdio.h>  
  6.   
  7. #define MAX_LINES           1000  
  8. #define MAX_CHAR_PER_LINE   100  
  9.   
  10. struct program_data{  
  11.     int interval;  
  12.     int display_timeout;  
  13. }data = { 60, 5 };  
  14. guint timer = 0, ticks = 0;  
  15. guint total_lines;  
  16. char life_knowledge[MAX_LINES][MAX_CHAR_PER_LINE];  
  17.   
  18. GdkPixbuf *pixbuf;  
  19. static int show_notification( const char* title, const char* context )  
  20. {  
  21.     NotifyNotification *n;  
  22.     n = notify_notification_new (title,  
  23.                                  context,  
  24.                                  NULL, NULL);  
  25.     notify_notification_set_timeout (n, data.display_timeout*1000); // 5 seconds  
  26.     notify_notification_set_icon_from_pixbuf( n, pixbuf );  
  27.     if (!notify_notification_show (n, NULL))  
  28.     {  
  29.         fprintf(stderr, "failed to send notification\n");  
  30.         return 1;  
  31.     }  
  32.     g_object_unref(G_OBJECT(n));  
  33.     return 0;  
  34. }  
  35.   
  36. static void show_helper()  
  37. {  
  38.     int i = rand() % total_lines;  
  39.     char buf[1000];  
  40.     int min = ticks / 60;  
  41.     int hour = min / 60;  
  42.     if( ticks > 10 ){  
  43.         sprintf( buf, "\n%s\n\t\n歇一歇吧!您使用电脑已经超过%d小时%d分。", life_knowledge[i], hour, min%60  );  
  44.     }else{  
  45.         sprintf( buf, "\n%s\n", life_knowledge[i]  );  
  46.     }  
  47.     show_notification("健康提示", buf );  
  48. }  
  49.   
  50. static void cb_set_interval(GtkWidget* widget, GtkSpinButton* spinner )  
  51. {  
  52.     data.interval = gtk_spin_button_get_value_as_int (spinner);  
  53. }  
  54.   
  55. static void cb_set_display_timeout(GtkWidget* widget, GtkSpinButton* spinner )  
  56. {  
  57.     data.display_timeout = gtk_spin_button_get_value_as_int (spinner);  
  58. }  
  59.   
  60. static void cb_save_config(GtkWidget* widget, gpointer win)  
  61. {  
  62.     //save config  
  63.     FILE* fp = fopen("./config""wb" );  
  64.     if(fp){  
  65.         fwrite( &data, sizeof(data), 1, fp );  
  66.         fclose(fp);  
  67.     }  
  68.     gtk_widget_destroy(win);  
  69. }  
  70.   
  71. static void show_configuration()  
  72. {  
  73.     GtkWidget *item = NULL;  
  74.     GtkWidget *win = NULL;  
  75.     GtkWidget *table = NULL;  
  76.     GtkAdjustment* adj = NULL;  
  77.   
  78.     /* Create the main window */  
  79.     win = gtk_window_new (GTK_WINDOW_TOPLEVEL);  
  80.     gtk_container_set_border_width (GTK_CONTAINER (win), 8);  
  81.     gtk_window_set_title (GTK_WINDOW (win), "Life Helper Configuration");  
  82.     gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_CENTER);  
  83.   
  84.     table = gtk_table_new( 4, 2, TRUE );  
  85.     gtk_container_add (GTK_CONTAINER (win), table);  
  86.   
  87.     item = gtk_label_new ("Interval (min) ");  
  88.     gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 1, 0, 1);  
  89.   
  90.     adj = (GtkAdjustment*)gtk_adjustment_new (data.interval, 1.0, 60.0*8, 1.0,  
  91.                           10.0, 0.0);  
  92.     item = gtk_spin_button_new (adj, 0, 0);  
  93.     gtk_table_attach_defaults( GTK_TABLE(table), item, 1, 2, 0, 1 );  
  94.     g_signal_connect( item, "value_changed", G_CALLBACK(cb_set_interval), item );  
  95.   
  96.     item = gtk_label_new ("Display Timeout (s) ");  
  97.     gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 1, 1, 2);  
  98.   
  99.     adj = (GtkAdjustment*)gtk_adjustment_new (data.display_timeout, 1.0, 15.0, 1.0,  
  100.                           2.0, 0.0);  
  101.     item = gtk_spin_button_new (adj, 0, 0);  
  102.     gtk_table_attach_defaults( GTK_TABLE(table), item, 1, 2, 1, 2 );  
  103.     g_signal_connect( item, "value_changed", G_CALLBACK(cb_set_display_timeout), item );  
  104.   
  105.     item = gtk_hseparator_new();  
  106.     gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 2, 2, 3);  
  107.   
  108.     item = gtk_button_new_from_stock (GTK_STOCK_SAVE);  
  109.     g_signal_connect (item, "clicked", G_CALLBACK(cb_save_config), win);  
  110.     gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 2, 3, 4);  
  111.   
  112.     gtk_widget_show_all (win);  
  113. }  
  114.   
  115.   
  116. void cb_show_helper()  
  117. {  
  118.     show_helper();  
  119. }  
  120.   
  121. void cb_configure()  
  122. {  
  123.     show_configuration();  
  124. }  
  125.   
  126. void cb_exit()  
  127. {  
  128.     gtk_main_quit();  
  129. }  
  130.   
  131. GtkWidget *menu;  
  132. void init_menu()  
  133. {  
  134.     menu =  gtk_menu_new();  
  135.     GtkWidget *item;  
  136.   
  137.     item = gtk_menu_item_new_with_label("Show Next");  
  138.     g_signal_connect(G_OBJECT(item), "activate",  
  139.                 G_CALLBACK(cb_show_helper), NULL);  
  140.     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);  
  141.   
  142.     /* 可爱的分割线 */  
  143.     item = gtk_separator_menu_item_new();  
  144.     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);  
  145.   
  146.     item = gtk_menu_item_new_with_label("Configure");  
  147.     g_signal_connect(G_OBJECT(item), "activate",  
  148.                 G_CALLBACK(cb_configure), NULL);  
  149.     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);  
  150.   
  151.     /* 可爱的分割线 */  
  152.     item = gtk_separator_menu_item_new();  
  153.     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);  
  154.   
  155.     item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);  
  156.     g_signal_connect(G_OBJECT(item), "activate",  
  157.                G_CALLBACK(cb_exit), NULL);  
  158.     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);  
  159. }  
  160.   
  161. void show_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer pos)  
  162. {  
  163.     gtk_menu_popup(GTK_MENU(menu),  
  164.                NULL,  
  165.                NULL,  
  166.                NULL,  
  167.                NULL,  
  168.                button,  
  169.                activate_time);  
  170.     gtk_widget_show_all(GTK_WIDGET(menu));  
  171. }  
  172.   
  173.   
  174. void init_system_tray()  
  175. {  
  176.     GtkStatusIcon* status_icon =   gtk_status_icon_new_from_pixbuf(pixbuf);  
  177.     if(!status_icon){  
  178.         fprintf(stderr, "failed to load icon file.\n" );  
  179.         exit( 1 );  
  180.     }  
  181.     gtk_status_icon_set_tooltip(status_icon, "生活小助手");  
  182.     gtk_status_icon_set_visible(status_icon, (gboolean)TRUE);  
  183.     init_menu();  
  184.     g_signal_connect(G_OBJECT(status_icon), "popup_menu",  
  185.         G_CALLBACK(show_menu), status_icon);  
  186. }  
  187.   
  188. static gint cb_timer(gpointer d)  
  189. {  
  190.     if( ticks++ % (data.interval*60) == 0 ){  
  191.         show_helper();  
  192.     }  
  193.     return TRUE; //continue  
  194. }  
  195.   
  196.   
  197. static void reload_text()  
  198. {  
  199.     int i;  
  200.     FILE* fp=fopen("./life.txt""r");  
  201.     if(!fp){  
  202.         fprintf(stderr, "failed to load text life.txt\n");  
  203.         exit(1);  
  204.     }  
  205.     for( i=0; !feof(fp) && i<MAX_LINES; i++ ){  
  206.         fgets(life_knowledge[i], MAX_CHAR_PER_LINE, fp );  
  207.     }  
  208.     total_lines = i;  
  209.     fclose(fp);  
  210. }  
  211.   
  212. int main (int argc, char *argv[])  
  213. {  
  214.     reload_text();  
  215.     srand(time(NULL));  
  216.     //load config  
  217.     FILE* fp = fopen("./config""rb" );  
  218.     if(fp){  
  219.         fread( &data, sizeof(data), 1, fp );  
  220.         fclose(fp);  
  221.     }  
  222.     gtk_init (&argc, &argv);  
  223.     notify_init("Life Helper");  
  224.     //Load my Bulb  
  225.     pixbuf = gdk_pixbuf_new_from_file("bulb.png", NULL );  
  226.     if(!pixbuf)  
  227.     {  
  228.         fprintf(stderr, "failed to load cmcclogin.png\n");  
  229.         return 1;  
  230.     }  
  231.   
  232.     //Load the system tray  
  233.     init_system_tray();  
  234.   
  235.     //ticks every second  
  236.     timer = gtk_timeout_add( 1000, (cb_timer), NULL );  
  237.   
  238.     gtk_main ();  
  239.     return 0;  
  240. }  

第一个Gtk写的实用小程序《健康提示小助手》》有14个想法

  1. zelinhehe

    太感谢你了。
    刚工作不久,有一个问题两天了没解决,在你这里找到了答案。再次谢谢你!

    回复

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据