GTK+浅谈之三简单计算器

一、简介

        简单的计算器,通过接受按键或点击事件将用户输入的信息送人完成简单的算术计算。

二、详解

1、计算器一

(1)代码
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
/* --- This is the LCD panel - the results --- */
#define BUF_SIZE 88
#define MAX_SIZE 120
static gdouble num1 = 0;
static gchar lastChar = (char) 0;
static gchar prevCmd = (char) 0;

GtkWidget *label;

typedef struct {
    char      *szLabel;    /* --- Label display on button --- */
    int       row;         /* --- Row to place the button --- */
    int       col;         /* --- Column to place the button --- */
    GtkWidget *widget;     /* --- Handle to the button --- */
}typCalculatorButton;
typCalculatorButton buttonList [] = {
    {"C",   1, 0, NULL},      /* --- Clear --- */
    {"CE",  1, 1, NULL},      /* --- Clear --- */
    {"/",   1, 3, NULL},      /* --- Division --- */

    {"7",   2, 0, NULL},      /* --- Digit --- */
    {"8",   2, 1, NULL},      /* --- Digit --- */
    {"9",   2, 2, NULL},      /* --- Digit --- */
    {"*",   2, 3, NULL},      /* --- Multiplication --- */
    {"%",   2, 4, NULL},      /* --- Percent --- */

    {"4",   3, 0, NULL},      /* --- Digit --- */
    {"5",   3, 1, NULL},      /* --- Digit --- */
    {"6",   3, 2, NULL},      /* --- Digit --- */
    {"-",   3, 3, NULL},      /* --- Subtraction --- */
    {"1/x", 3, 4, NULL},      /* --- 1/x --- */

    {"1",   4, 0, NULL},      /* --- Digit --- */
    {"2",   4, 1, NULL},      /* --- Digit --- */
    {"3",   4, 2, NULL},      /* --- Digit --- */
    {"+",   4, 3, NULL},      /* --- Addition --- */
    {"sqrt",4, 4, NULL},      /* --- Square root --- */

    {"+/-", 5, 0, NULL},      /* --- Negate value --- */
    {"0",   5, 1, NULL},      /* --- zero --- */
    {".",   5, 2, NULL},      /* --- Decimal --- */
    {"=",   5, 3, NULL},      /* --- Equals/total --- */
    {"x^2", 5, 4, NULL},      /* --- Squared --- */
};

gint CloseAppWindow(GtkWidget *widget, gpointer data)
{
    gtk_main_quit ();
    return FALSE;
}
static void trim_trailing_zeros (char *szDigits)
{
    int nIndex;
    int bDecimal = FALSE;
    int nPos = -1;
    for (nIndex = 0; nIndex < strlen (szDigits); nIndex++) {
        if (szDigits[nIndex] == '.') {
            bDecimal = TRUE;
        }
        if (bDecimal) {
            if (szDigits[nIndex] == '0') {
                if (nPos < 0) {
                    nPos = nIndex;
                }
            }
        }
    }
    if (nPos > 0) {
        szDigits[nPos] = (char) 0;
        if (szDigits[nPos -1] == '.') {
            szDigits[nPos -1] = (char)0;
        }
    }
}

static void trim_leading_zeros(char *szDigits)
{
    gint nPos;
    if (szDigits == NULL) return;
    for (nPos = 0; (szDigits[nPos] && szDigits[nPos] == '0'); nPos++) {
        if (isdigit(szDigits[nPos+1])) {
            szDigits[nPos] = ' ';
        }
    }
}
int command (char ch)
{
    switch (ch) {
        case '+':
        case '-':
        case '/':
        case '*':
        case '=':
            return (TRUE);
    }
    return (FALSE);
}
void handle_digit(char *str, char ch)
{
    char *labelText;
    char buffer[BUF_SIZE] = {0};
    char result[MAX_SIZE] = {0};
    int  len;
    if (command(lastChar)) {
        gtk_label_set (GTK_LABEL (label), "");
        if (lastChar == '=') {
            lastChar = (char) 0;
            prevCmd = (char) 0;
        }
    }
    gtk_label_get(GTK_LABEL (label), &labelText);
    strcpy (buffer, labelText);
    len = strlen (buffer);
    buffer[len] = (gchar)ch;
    buffer[len+1] = (gchar)0;
    trim_leading_zeros(buffer);
    sprintf (result, "<span foreground='blue' font_desc='15'>%s</span>", buffer);
    gtk_label_set_markup(GTK_LABEL(label), result);
    //gtk_label_set (GTK_LABEL (label), (char *) buffer);
}

void maybe_unary_operation (char *str)
{
    gchar *labelText;
    gchar buffer[BUF_SIZE] = {0};
    gchar result[MAX_SIZE] = {0};
    gdouble num2;

    gtk_label_get (GTK_LABEL (label), &labelText);
    num2 = atof (labelText);
    if (strcmp (str, "%") == 0) {
        num2 = num2 / 100;
    }
    else if (strcmp (str, "1/x") == 0) {
        if (num2 == 0) {
            return;
        }
        num2 = 1 / num2;
    }
    else if (strcmp (str, "sqrt") == 0) {
        num2 = sqrt((double) num2);
    }
    else if (strcmp (str, "x^2") == 0) {
        num2 = num2 * num2;
    }
    sprintf (buffer, "%f", (gdouble) num2);
    trim_trailing_zeros (buffer);
    trim_leading_zeros (buffer);
    sprintf (result, "<span foreground='blue' font_desc='15'>%s</span>", buffer);
    gtk_label_set_markup(GTK_LABEL(label), result);
    //gtk_label_set (GTK_LABEL (label), buffer);
}
void handle_binary_operation()
{
    gchar buffer[BUF_SIZE] = {0};
    gchar result[MAX_SIZE] = {0};
    gchar *labelText;
    gdouble num2;
    gtk_label_get (GTK_LABEL (label), &labelText);
    num2 = atof (labelText);
    switch (prevCmd) {
        case '+':
            num1 = num1 + num2;
            break;

        case '-':
            num1 = num1 - num2;
            break;

        case '*':
            num1 = num1 * num2;
            break;

        case '/':
            num1 = num1 / num2;
            break;

        case '=':
            num1 = num2;
            break;

        default:
            num1 = num2;
            break;
    }
    sprintf (buffer, "%f", (gdouble) num1);
    trim_trailing_zeros(buffer);
    trim_leading_zeros(buffer);
    sprintf (result, "<span foreground='blue' font_desc='15'>%s</span>", buffer);
    gtk_label_set_markup(GTK_LABEL(label), result);
}

void button_clicked(GtkWidget *widget, gpointer data)
{
    gchar ch = *((gchar *) data);
    gchar *str = (gchar *)data;
    if ((isdigit (ch) || ch == '.') && strlen(str) == 1) {
        handle_digit(str, ch);
    }
    else {
        if (strcmp(str, "CE") == 0) {
            gtk_label_set_markup(GTK_LABEL(label), "<span foreground='blue' font_desc='15'>0</span>");
            return;
        }
        else if (strcmp (str, "C") == 0) {
            prevCmd = (char) 0;
            lastChar = (char) 0;
            gtk_label_set_markup(GTK_LABEL(label), "<span foreground='blue' font_desc='15'>0</span>");
            return;
        }
        else {
            maybe_unary_operation(str);
        }
        handle_binary_operation();
        prevCmd = ch;
    }
    lastChar = ch;
}

GtkWidget *create_button (GtkWidget *table, char *szLabel, int row, int column)
{
    GtkWidget *button;
    button = gtk_button_new_with_label (szLabel);
    gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (button_clicked), szLabel);
    gtk_table_attach(GTK_TABLE (table), button, column, column+1, row, row + 1,
                     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 5, 5);
    return button;
}

void create_calculator_buttons (GtkWidget *table)
{
    gint nIndex;
    for (nIndex = 0; nIndex < sizeof (buttonList)/sizeof (typCalculatorButton); nIndex++) {
        buttonList[nIndex].widget = create_button(table, buttonList[nIndex].szLabel, buttonList[nIndex].row, buttonList[nIndex].col);
    }
}

void key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
    gint nIndex;
    for (nIndex = 0; nIndex < sizeof (buttonList)/sizeof (typCalculatorButton); nIndex++) {
        if (strcmp(event->string, buttonList[nIndex].szLabel) == 0) {
            gtk_widget_grab_focus (buttonList[nIndex].widget);
            gtk_button_clicked(GTK_BUTTON (buttonList[nIndex].widget));
            return;
        }
    }
}
int main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *table;
    GtkWidget * frame;
    /* --- GTK initialization --- */
    gtk_init (&argc, &argv);
    /* --- Create the calculator window --- */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    /* --- Give the window a title. --- */
    gtk_window_set_title (GTK_WINDOW (window), "Calculator");
    /* --- Set the window size. --- */
    gtk_widget_set_usize (window, 300, 300);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    /* --- We care if a key is pressed --- */
    gtk_signal_connect (GTK_OBJECT (window), "key_press_event", GTK_SIGNAL_FUNC (key_press), NULL);
    /* --- You should always remember to connect the delete event to the main window. --- */
    gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (CloseAppWindow), NULL);
    /* --- Create a 5x5 table for the items in the calculator. --- */
    table = gtk_table_new (5, 5, TRUE);
    /* --- Create the calculator buttons. --- */
    create_calculator_buttons (table);
    /* --- Create the calculator LED --- */
    label = gtk_label_new (NULL);
    gtk_label_set_markup(GTK_LABEL(label), "<span foreground='blue' font_desc='15'>0</span>");
    frame = gtk_frame_new(NULL);
    gtk_container_add(GTK_CONTAINER(frame),label);
    gtk_misc_set_alignment (GTK_MISC (label), 1, .5);
    gtk_table_attach_defaults (GTK_TABLE (table), frame, 0, 5, 0, 1);
    /* --- Make them visible --- */
    gtk_container_add (GTK_CONTAINER (window), table);

    gtk_widget_show_all(window);
    gtk_main ();
    return 0;
}
(2)编译运行
gcc -o calculator calculator_one.c `pkg-config --libs --cflags gtk+-2.0`
   

2、计算器二

(1)代码
/*gcc -o calculator calculator_two.cpp `pkg-config --cflags --libs gtk+-2.0`*/
#include <gtk/gtk.h>
#include <stdlib.h>
static GtkWidget *entry;
gint count = 0;
gdouble nn = 0;
gdouble mm = 0;
gint s = 0;
gboolean first = TRUE;
gboolean have_dot = FALSE;
gboolean have_result = FALSE;
gchar number[100];

void clear_all()
{
    gint i;
    nn = 0;
    mm = 0;
    s = 0;
    count = 0;
    first = TRUE;
    have_dot = FALSE;
    have_result = FALSE;
    for (i = 0; i < sizeof(number); i++)
        number[i] = '\0';
    gtk_entry_set_text(GTK_ENTRY(entry), "");
}

void on_clear_clicked(GtkButton *button, gpointer data)
{
    clear_all();
}
void on_num_clicked(GtkButton *button, gpointer data)
{
    const gchar *num;
    gint i;
    if (have_result) clear_all();
    if (count == 6) return;
    count++;
    num = gtk_button_get_label(GTK_BUTTON(button));
    i = g_strlcat(number, num, 100);
    if (first) {
        nn = g_ascii_strtod(number, NULL);
    }
    else
        mm = g_ascii_strtod(number, NULL);
    gtk_entry_set_text(GTK_ENTRY(entry), number);
}
void on_suan_clicked(GtkButton *button, gpointer data)
{
    gint i;
    s = GPOINTER_TO_INT(data);
    first = FALSE;
    count = 0;
    have_dot = FALSE;
    gtk_entry_set_text(GTK_ENTRY(entry), "");
    for (i = 0; i < sizeof(number); i++)
        number[i] = '\0';
}
void on_dot_clicked(GtkButton *button, gpointer data)
{
    gint i;
    if (have_result) clear_all();
    if (have_dot == FALSE) {
        have_dot = TRUE;
        i = g_strlcat(number, ".", 100);
        gtk_entry_set_text(GTK_ENTRY(entry), number);
    }
}
void on_eq_clicked(GtkButton *button, gpointer data)
{
    gdouble numb;
    gchar num[100];
    gchar *result;
    switch(s) {
    case 1:
        numb = nn + mm;
        break;
    case 2:
        numb = nn - mm;
        break;
    case 3:
        numb = nn * mm;
        break;
    case 4:
        numb = nn / mm;
        break;
    }
    result = g_ascii_dtostr(num, 100, numb);
    have_result = TRUE;
    gtk_entry_set_text(GTK_ENTRY(entry), result);
}

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *vbox;
    GtkWidget *hbox, *hbox1, *hbox2, *hbox3, *hbox4;
    GtkWidget *button;
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
    gtk_window_set_title(GTK_WINDOW(window), "计算器");
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);    //postion
    gtk_widget_set_usize (window, 230, 230);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), vbox);

    entry = gtk_entry_new();
    gtk_widget_set_direction(entry, GTK_TEXT_DIR_RTL);
    gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 5);

    hbox = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
    button = gtk_button_new_with_label("CE");
    gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_clear_clicked), NULL);

    hbox1 = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 5);
    button = gtk_button_new_with_label("3");
    gtk_box_pack_start(GTK_BOX(hbox1), button, TRUE, TRUE, 5);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    button = gtk_button_new_with_label("2");
    gtk_box_pack_start(GTK_BOX(hbox1), button, TRUE, TRUE, 5);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    button = gtk_button_new_with_label("1");
    gtk_box_pack_start(GTK_BOX(hbox1), button, TRUE, TRUE, 5);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    button = gtk_button_new_with_label("+");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_suan_clicked), (gpointer)1);
    gtk_box_pack_start(GTK_BOX(hbox1), button, TRUE, TRUE, 5);

    hbox2 = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 5);
    button = gtk_button_new_with_label("6");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox2), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("5");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox2), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("4");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox2), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("-");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_suan_clicked), (gpointer)2);
    gtk_box_pack_start(GTK_BOX(hbox2), button, TRUE, TRUE, 5);

    hbox3 = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox3, FALSE, FALSE, 5);
    button = gtk_button_new_with_label("9");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox3), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("8");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox3), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("7");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox3), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("*");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_suan_clicked), (gpointer)3);
    gtk_box_pack_start(GTK_BOX(hbox3), button, TRUE, TRUE, 5);

    hbox4 = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox4, FALSE, FALSE, 5);
    button = gtk_button_new_with_label("0");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_num_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox4), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label(".");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_dot_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox4), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("=");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_eq_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(hbox4), button, TRUE, TRUE, 5);
    button = gtk_button_new_with_label("/");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_suan_clicked), (gpointer)4);
    gtk_box_pack_start(GTK_BOX(hbox4), button, TRUE, TRUE, 5);

    gtk_widget_show_all(window);
    gtk_main();
    return TRUE;
}
(2)编译并运行
gcc -o calculator calculator_two.c `pkg-config --cflags --libs gtk+-2.0`
   

三、总结

(1)上述计算器只是简单的实现,都存在不同的问题和功能的不完善,感兴趣的读者可自己添加。
(2)源码可从csdn上下载:http://download.csdn.net/detail/taiyang1987912/9094107
(3)若有建议,请留言,在此先感谢!
 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦2号

博文不易,支持的请给予小小打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值