|
二、实践阶段
有了上面的概念后下面的实践就好办了。
第一步,创建主程序,程序中加入按键1、2、3、4、5、6、7、8、9、0、+、-、*、/、=、clear、help加入数据显示行。并用vbox,hbox进行布局。连接按键和处理程序。代码如下:
int main ( int argc , char* argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox,*hbox1,*hbox2,*hbox3;
GtkWidget *button;
GtkWidget *label;
gtk_init(&argc,&argv);
s.count =0;
s.first_data =TRUE;
s.fi_dot =FALSE;
s.se_dot =FALSE;
s.cac_result_flag =FALSE;
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),"Calculator V1.0");
gtk_window_set_default_size(GTK_WINDOW(window),150,150);
gtk_container_set_border_width(GTK_CONTAINER(window),10);
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
gtk_container_add(GTK_CONTAINER(window),vbox);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,5);
//第一行 计算器标号和清除按钮
label = gtk_label_new("Calculator");
gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,5);
button = gtk_button_new_with_label("C");
gtk_box_pack_start(GTK_BOX(hbox),button,TRUE,TRUE,5);
//信号连接 连接按钮和响应函数
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(clear_clicked),NULL);
button = gtk_button_new_with_label("?");
gtk_box_pack_start(GTK_BOX(hbox),button,TRUE,TRUE,5);
//信号连接 连接按钮和响应函数
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(help_clicked),NULL);
//第二行 输入显示 第二第三第四第五行等距离 使用vbox 和hbox
input_enter = gtk_entry_new();
gtk_widget_set_direction(input_enter,GTK_TEXT_DIR_RTL);
//每个按钮都是以同样的方式组装到横向盒里的,这里只有一个对象
gtk_box_pack_start(GTK_BOX(vbox),input_enter,FALSE,FALSE,5);
//第三行 0,1,2,3,4,+号
hbox1 = gtk_box_new(FALSE,0);
//hbox1 组装vbox盒里的,这样形成一行
gtk_box_pack_start(GTK_BOX(vbox),hbox1,FALSE,FALSE,5);
button = gtk_button_new_with_label("0");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);
button = gtk_button_new_with_label("1");
g_signal_connect(G_OBJECT(button),"clicked",//按钮连接到相关响应函数
G_CALLBACK(number_clicked),NULL);
//button “1” 装进hbox1盒子,同样后面的“2”, “3”,“4”,“5”,“+”都装到hbox1 这样一行中有6个按钮
//其他行同样道理
gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);
button = gtk_button_new_with_label("2");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,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(number_clicked),NULL);
button = gtk_button_new_with_label("4");
gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
button = gtk_button_new_with_label("+");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(operator_clicked),(gpointer)1);
gtk_box_pack_start(GTK_BOX(hbox1),button,TRUE,TRUE,5);
//第四行5,6,7,8,9,-号
hbox2 = gtk_box_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(vbox),hbox2,FALSE,FALSE,5);
button = gtk_button_new_with_label("5");
gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
button = gtk_button_new_with_label("6");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);
button = gtk_button_new_with_label("7");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);
button = gtk_button_new_with_label("8");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_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(operator_clicked),(gpointer)2);
gtk_box_pack_start(GTK_BOX(hbox2),button,TRUE,TRUE,5);
//第五行 *,9,.,=,/
hbox3 = gtk_box_new(FALSE,0);
button = gtk_button_new_with_label("9");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(number_clicked),NULL);
gtk_box_pack_start(GTK_BOX(hbox3),button,TRUE,TRUE,5);
gtk_box_pack_start(GTK_BOX(vbox),hbox3,FALSE,FALSE,5);
button = gtk_button_new_with_label("*");
g_signal_connect(G_OBJECT(button),"clicked",
G_CALLBACK(operator_clicked),(gpointer)3);
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(dot_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(equ_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(operator_clicked),(gpointer)4);
gtk_box_pack_start(GTK_BOX(hbox3),button,TRUE,TRUE,5);
//gtk_widget_show_all 显示
gtk_widget_show_all(window);
//主循环
gtk_main();
return FALSE;
}
第二步,进行数据处理:
采用一个结构体保存过程数据:
count限制一下输入位数,s保存是加减乘除等计算方法的一种,first_data指示是输入计算数据的两个数的第一个还是第二个,因为输入的数据会保存到不同的数组numberFi 或numberSe中。fi_dot、se_dot为了保证一个数据中只有一个小数点。
每次计算开始的时候会清除所有数据到开始阶段如下:
Help按钮的消息框:
clear按钮:
加减乘除等操作符响应函数:
数字按钮响应函数:
根据先前是否按下s.first_data把数据保存到s.numberFi或 s.numberSe中。
当然如果是有s.cac_result_flag为真,也就是如果计算结果完成了或程序刚启动,就清除数据到计算前状态。
小数点按钮响应函数:
避免多个小数点在一个数字中。
根据先前是否按下s.first_data把数据保存到s.numberFi或 s.numberSe中。
当然如果是有s.cac_result_flag为真,也就是如果计算结果完成了或程序刚启动,就清除数据到计算前状态。
=符合响应函数:
根据符号和s.numberFi、s.numberSe计算结果并显示。
s.cac_result_flag标记为真,下次按钮按下就会清除数据准备计算。
#include <gtk/gtk.h>
#include <stdlib.h>
static GtkWidget *input_enter; //定义单行输入控件来显示输入输出的数字
struct ss
{
gint count; //计位
gint s; //算法
gboolean first_data; //首次输入
gboolean fi_dot; //是否有小数点
gboolean se_dot; //是否有小数点
gboolean cac_result_flag; //是否有结果输出
gchar numberFi[100]; //保存用户输入的数字
gchar numberSe[100]; //保存用户输入的数字
} s;
void clear (void)
{
//重新计算清除标记
gtk_entry_set_text(GTK_ENTRY(input_enter),"");
s.s = 0;
s.count = 0 ;
s.first_data = TRUE;
s.fi_dot = FALSE;
s.se_dot = FALSE;
s.cac_result_flag = FALSE;
for(gint i = 0 ; i < 100 ; i++)
{
s.numberFi[i] = 0;
s.numberSe[i] = 0;
}
}
void help_clicked (GtkWidget *widget, gpointer window)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new(window,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"The calculator app provides simple operations of addition, subtraction, multiplication, and division.");
gtk_window_set_title(GTK_WINDOW(dialog), "HELP");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
void number_clicked (GtkButton* button,gpointer data)
{ //当数定键按下时执行
const gchar *num;
if(s.cac_result_flag)//按下数字键和小数点键时显示结果清零,并且数据清理重新开始计数
clear();
if(s.count == 8) return; //限制输入位数
s.count++;
num = gtk_button_get_label(GTK_BUTTON(button));//取数
if(s.first_data)
{
g_strlcat(s.numberFi,num,100);//保存
gtk_entry_set_text(GTK_ENTRY(input_enter),s.numberFi);//显示
}
else
{
g_strlcat(s.numberSe,num,100);//保存
gtk_entry_set_text(GTK_ENTRY(input_enter),s.numberSe);//显示
}
}
void dot_clicked (GtkButton* button,gpointer data)
{ //当小数点按下时
if(s.cac_result_flag)//按下数字键和小数点键时显示结果清零,并且数据清理重新开始计数
clear();
if(s.first_data)
{
if(s.fi_dot == FALSE) //每个数字串只一次按下小数点
{
s.fi_dot = TRUE;
g_strlcat(s.numberFi,".",100);
gtk_entry_set_text(GTK_ENTRY(input_enter),s.numberFi);
}
}
else
{
if(s.se_dot == FALSE) //每个数字串只一次按下小数点
{
s.se_dot =TRUE;
g_strlcat(s.numberSe,".",100);
gtk_entry_set_text(GTK_ENTRY(input_enter),s.numberSe);
}
}
//如果有小数点则不输出
}
void clear_clicked (GtkButton* button,gpointer data)
{
clear();//全部清除
}
void operator_clicked (GtkButton* button,gpointer data)
{
// +,-,*,/ 按下时
switch(GPOINTER_TO_INT(data))
{
case 1: //"+"
s.s = 1;
gtk_entry_set_text(GTK_ENTRY(input_enter),"");
s.first_data = FALSE ; s.count = 0; break;
case 2: //"-"
s.s = 2;
gtk_entry_set_text(GTK_ENTRY(input_enter),"");
s.first_data = FALSE ; s.count = 0; break;
case 3: //"*"
s.s = 3;
gtk_entry_set_text(GTK_ENTRY(input_enter),"");
s.first_data = FALSE ; s.count = 0; break;
case 4: //"/"
s.s = 4;
gtk_entry_set_text(GTK_ENTRY(input_enter),"");
s.first_data = FALSE ; s.count = 0; break;
}
}
void equ_clicked (GtkButton* button,gpointer data)
{ //当等号键按钮按下时
double numb=0;
gchar num[100];
gchar *result;
gdouble n = strtod(s.numberFi,NULL);//数一转换
gdouble m = strtod(s.numberSe,NULL);//数二转换
switch(s.s)
{
case 1: //"+
numb = n+m;
break;
case 2: //"-"
numb = n-m;
break;
case 3: //"*"
numb = n*m;
break;
case 4: //"/"
numb = n/m;
break;
}
result = g_ascii_dtostr(num,100,numb);
gtk_entry_set_text(GTK_ENTRY(input_enter),result);
s.cac_result_flag = TRUE;
}
三、显示结果: