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

高手免进!!!

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

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

配置界面:

 

源代码:

#include <stdlib.h>
#include <gtk/gtk.h>
#include <time.h>
#include <libnotify/notify.h>
#include <stdio.h>

#define MAX_LINES           1000
#define MAX_CHAR_PER_LINE   100

struct program_data{
    int interval;
    int display_timeout;
}data = { 60, 5 };
guint timer = 0, ticks = 0;
guint total_lines;
char life_knowledge[MAX_LINES][MAX_CHAR_PER_LINE];

GdkPixbuf *pixbuf;
static int show_notification( const char* title, const char* context )
{
    NotifyNotification *n;
    n = notify_notification_new (title,
                                 context,
                                 NULL, NULL);
    notify_notification_set_timeout (n, data.display_timeout*1000); // 5 seconds
    notify_notification_set_icon_from_pixbuf( n, pixbuf );
    if (!notify_notification_show (n, NULL))
    {
        fprintf(stderr, "failed to send notification\n");
        return 1;
    }
    g_object_unref(G_OBJECT(n));
    return 0;
}

static void show_helper()
{
    int i = rand() % total_lines;
    char buf[1000];
    int min = ticks / 60;
    int hour = min / 60;
    if( ticks > 10 ){
        sprintf( buf, "\n%s\n\t\n歇一歇吧!您使用电脑已经超过%d小时%d分。", life_knowledge[i], hour, min%60  );
    }else{
        sprintf( buf, "\n%s\n", life_knowledge[i]  );
    }
    show_notification("健康提示", buf );
}

static void cb_set_interval(GtkWidget* widget, GtkSpinButton* spinner )
{
    data.interval = gtk_spin_button_get_value_as_int (spinner);
}

static void cb_set_display_timeout(GtkWidget* widget, GtkSpinButton* spinner )
{
    data.display_timeout = gtk_spin_button_get_value_as_int (spinner);
}

static void cb_save_config(GtkWidget* widget, gpointer win)
{
    //save config
    FILE* fp = fopen("./config", "wb" );
    if(fp){
        fwrite( &data, sizeof(data), 1, fp );
        fclose(fp);
    }
    gtk_widget_destroy(win);
}

static void show_configuration()
{
    GtkWidget *item = NULL;
    GtkWidget *win = NULL;
    GtkWidget *table = NULL;
    GtkAdjustment* adj = NULL;

    /* Create the main window */
    win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_container_set_border_width (GTK_CONTAINER (win), 8);
    gtk_window_set_title (GTK_WINDOW (win), "Life Helper Configuration");
    gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_CENTER);

    table = gtk_table_new( 4, 2, TRUE );
    gtk_container_add (GTK_CONTAINER (win), table);

    item = gtk_label_new ("Interval (min) ");
    gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 1, 0, 1);

    adj = (GtkAdjustment*)gtk_adjustment_new (data.interval, 1.0, 60.0*8, 1.0,
					      10.0, 0.0);
    item = gtk_spin_button_new (adj, 0, 0);
    gtk_table_attach_defaults( GTK_TABLE(table), item, 1, 2, 0, 1 );
    g_signal_connect( item, "value_changed", G_CALLBACK(cb_set_interval), item );

    item = gtk_label_new ("Display Timeout (s) ");
    gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 1, 1, 2);

    adj = (GtkAdjustment*)gtk_adjustment_new (data.display_timeout, 1.0, 15.0, 1.0,
					      2.0, 0.0);
    item = gtk_spin_button_new (adj, 0, 0);
    gtk_table_attach_defaults( GTK_TABLE(table), item, 1, 2, 1, 2 );
    g_signal_connect( item, "value_changed", G_CALLBACK(cb_set_display_timeout), item );

    item = gtk_hseparator_new();
    gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 2, 2, 3);

    item = gtk_button_new_from_stock (GTK_STOCK_SAVE);
    g_signal_connect (item, "clicked", G_CALLBACK(cb_save_config), win);
    gtk_table_attach_defaults (GTK_TABLE (table), item, 0, 2, 3, 4);

    gtk_widget_show_all (win);
}


void cb_show_helper()
{
    show_helper();
}

void cb_configure()
{
    show_configuration();
}

void cb_exit()
{
    gtk_main_quit();
}

GtkWidget *menu;
void init_menu()
{
    menu =  gtk_menu_new();
    GtkWidget *item;

    item = gtk_menu_item_new_with_label("Show Next");
    g_signal_connect(G_OBJECT(item), "activate",
                G_CALLBACK(cb_show_helper), NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

    /* 可爱的分割线 */
    item = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

    item = gtk_menu_item_new_with_label("Configure");
    g_signal_connect(G_OBJECT(item), "activate",
                G_CALLBACK(cb_configure), NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

    /* 可爱的分割线 */
    item = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
    g_signal_connect(G_OBJECT(item), "activate",
               G_CALLBACK(cb_exit), NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
}

void show_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer pos)
{
    gtk_menu_popup(GTK_MENU(menu),
               NULL,
               NULL,
               NULL,
               NULL,
               button,
               activate_time);
    gtk_widget_show_all(GTK_WIDGET(menu));
}


void init_system_tray()
{
    GtkStatusIcon* status_icon =   gtk_status_icon_new_from_pixbuf(pixbuf);
    if(!status_icon){
        fprintf(stderr, "failed to load icon file.\n" );
        exit( 1 );
    }
    gtk_status_icon_set_tooltip(status_icon, "生活小助手");
    gtk_status_icon_set_visible(status_icon, (gboolean)TRUE);
    init_menu();
    g_signal_connect(G_OBJECT(status_icon), "popup_menu",
        G_CALLBACK(show_menu), status_icon);
}

static gint cb_timer(gpointer d)
{
    if( ticks++ % (data.interval*60) == 0 ){
        show_helper();
    }
    return TRUE; //continue
}


static void reload_text()
{
    int i;
    FILE* fp=fopen("./life.txt", "r");
    if(!fp){
        fprintf(stderr, "failed to load text life.txt\n");
        exit(1);
    }
    for( i=0; !feof(fp) && i<MAX_LINES; i++ ){
        fgets(life_knowledge[i], MAX_CHAR_PER_LINE, fp );
    }
    total_lines = i;
    fclose(fp);
}

int main (int argc, char *argv[])
{
    reload_text();
    srand(time(NULL));
    //load config
    FILE* fp = fopen("./config", "rb" );
    if(fp){
        fread( &data, sizeof(data), 1, fp );
        fclose(fp);
    }
    gtk_init (&argc, &argv);
    notify_init("Life Helper");
    //Load my Bulb
    pixbuf = gdk_pixbuf_new_from_file("bulb.png", NULL );
    if(!pixbuf)
    {
        fprintf(stderr, "failed to load cmcclogin.png\n");
        return 1;
    }

    //Load the system tray
    init_system_tray();

    //ticks every second
    timer = gtk_timeout_add( 1000, (cb_timer), NULL );

    gtk_main ();
    return 0;
}


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

  1. zelinhehe

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

    回复

发表回复

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

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