您的位置:首页 > 移动开发 > 微信开发

一个五脏俱全的Gtk小程序

2014-04-21 17:15 155 查看
refer from:http://tzc.is-programmer.com/posts/534.html

本人自从学习Gtk以来,一直没能做一个像模像样的例子,前段时间抽空写了一个小程序,大概800多行,是调用Gtk和GLib库共同编译的,贴到这里和大家分享:

#include<gtk/gtk.h>

#include<glib.h>

#include<stdio.h>

#include<malloc.h>

#include<math.h>

enum /*定义图形的类型*/

{

PIX_DRAW=1, /*类型-点*/

LINE_DRAW,

CIRCLE_DRAW,

RECT_DRAW,

POLY_DRAW

};

typedef struct /*定义含树视图和绘图区的结构体,以便回调函数传递参数*/

{

GtkWidget *tree_view;

GtkWidget *draw_area;

}tree_drawing;

typedef struct /*定义含树视图、绘图区和文本输入框的结构体,以便回调函数传递参数*/

{

GtkWidget *window;

GtkWidget *view;

GtkWidget *entry;

}wview;

typedef struct /*为方便参数传递而创建的结构体*/

{

GtkWidget *window;

GtkWidget *view;

GtkWidget *entry;

GtkWidget *draw_area;

}wdview;

typedef struct _2D_POINT /*定义二维数据点结构体*/

{

float x,y;

}_2d_point;

/*------------定义全局变量--------------*/

double width=100.0,height=100.0; /*定义系统长宽,这里与窗口窗宽无关*/

int draw_type=0; /*定义图像类型*/

GSList *prt=NULL; /*定义存放数据的链表*/

GtkTreeModel *model; /*定义树视图模型*/

GtkTreeStore *tree_store; /*定义树形存储*/

GtkTreeIter top_pix,top_line,top_circle,top_rect,top_poly,other; /*定义树视图的项,以便添加元素*/

/*-----------函数声明部分------------------*/

GtkTreeView* create_tree(void); /*创建树视图*/

GtkTreeModel* create_model(void); /*创建树视图模型*/

void get_new_file(GtkWidget *button,wview *wv);/*获得文件名,并修改树视图显示*/

void create_file(GtkWidget *create_file_button,GtkWidget *view);/*创建文件菜单的回调函数*/

void get_import_file(GtkWidget* button,wdview *wdv); /*获得导入文件名,并修改树视图和绘图区显示*/

void messagebox(const char *str); /*消息提示框,用于提示相关信息*/

void import_file(GtkWidget *import_file_button,tree_drawing *td);/*导入文件菜单的回调函数*/

void export_file(GtkWidget *export_file_button,GtkWidget *view);/*导出文件菜单的回调函数*/

void enlarge_obj(GtkWidget *enlarge,GtkWidget *data);/*工具栏中放大按钮的回调函数,修改绘图区显示*/

void deflate_obj(GtkWidget *deflate,GtkWidget *data);/*工具栏中缩小按钮的回调函数,修改绘图区显示*/

void draw_pix(void); /*draw菜单下,points菜单的回调函数*/

void draw_line(void); /*Line菜单的回调函数*/

void draw_circle(void); /*Circle菜单的回调函数*/

void draw_rect(void); /*Rectagle菜单的回调函数*/

void draw_poly(void); /*Plygon菜单的回调函数*/

void draw_prt(GtkWidget *data); /*在绘图区中按照图像类型,将链表内容绘制出来,修改绘图区显示*/

/*下面这几个函数都没实现,这里不做具体介绍*/

/*

void show_part(GtkWidget *view,GtkWidget *draw_area);

void hide_part(GtkWidget *view,GtkWidget *draw_are);

void del_part(GtkWidget *view,GtkWidget *draw_area);

void modify_part(GtkWidget *view,GtkWidget *draw_area);

GtkWidget* pop_menu(GtkWidget *draw_area);

static gboolean view_press(GtkWidget *widget,GdkEventButton *event,GtkWidget *menu);

*/

/*-----------函数定义部分------------*/

/*

GtkWidget* pop_menu(GtkWidget *draw_area)

{

GtkWidget *file_menu;

GtkWidget *show_item,*hide_item,*del_item,*modify_item;

show_item=gtk_menu_item_new_with_label("show");

hide_item=gtk_menu_item_new_with_label("hide");

del_item=gtk_menu_item_new_with_label("delete");

modify_item=gtk_menu_item_new_with_label("modify");

gtk_menu_append(GTK_MENU(file_menu),show_item);

gtk_menu_append(GTK_MENU(file_menu),hide_item);

gtk_menu_append(GTK_MENU(file_menu),del_item);

gtk_menu_append(GTK_MENU(file_menu),modify_item);

g_signal_connect_swapped(G_OBJECT(show_item),"activate",G_CALLBACK(show_part),draw_area);

g_signal_connect_swapped(G_OBJECT(hide_item),"activate",G_CALLBACK(hide_part),draw_area);

g_signal_connect_swapped(G_OBJECT(del_item),"activate",G_CALLBACK(del_part),draw_area);

g_signal_connect_swapped(G_OBJECT(modify_item),"activate",G_CALLBACK(modify_part),draw_area);

return file_menu;

}

void show_part(GtkWidget *view,GtkWidget *draw_area)

{

}

void hide_part(GtkWidget *view,GtkWidget *draw_are)

{

}

void del_part(GtkWidget *view,GtkWidget *draw_area)

{

}

void modify_part(GtkWidget *view,GtkWidget *draw_area)

{

}

*/

/*上面几个函数都还没实现,由于事件问题,在这里就不具体实现了*/

/*-----------函数定义部分-------------*/

/*创建树视图,向里面添加列,并调用树视图模型创建函数完成树视图的创建,

* 输入参数:无

* 输出参数:树视图构件tree_view

* 日期:2007-4-7修改*/

GtkTreeView* create_tree(void)

{

GtkWidget *tree_view;

GtkTreeViewColumn *col;

GtkCellRenderer *cell;

tree_view=gtk_tree_view_new();

col=gtk_tree_view_column_new();

gtk_tree_view_column_set_title(col,"part");

gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view),col);

cell=gtk_cell_renderer_text_new();

//g_object_set(cell,"editable",TRUE,NULL);

//g_signal_connect(cell,"edited",G_CALLBACK(cell_edited),NULL);

gtk_tree_view_column_pack_start(col,cell,TRUE);

gtk_tree_view_column_add_attribute(col,cell,"text",0);

model=create_model();

gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view),model);

return GTK_TREE_VIEW(tree_view);

}

/*创建树视图模型,向tree_store里面添加条目

* 输入参数:无

* 输出参数:树视图模型tree_store

* 日期:2007-4-7修改*/

GtkTreeModel* create_model()

{

tree_store=gtk_tree_store_new(1,G_TYPE_STRING);

//添加树的项

gtk_tree_store_append(tree_store,&top_pix,NULL);

gtk_tree_store_set(tree_store,&top_pix,

0,"Points",-1);

gtk_tree_store_append(tree_store,&top_line,NULL);

gtk_tree_store_set(tree_store,&top_line,

0,"Lines",-1);

gtk_tree_store_append(tree_store,&top_circle,NULL);

gtk_tree_store_set(tree_store,&top_circle,

0,"Circles",-1);

gtk_tree_store_append(tree_store,&top_rect,NULL);

gtk_tree_store_set(tree_store,&top_rect,

0,"Rectangles",-1);

gtk_tree_store_append(tree_store,&top_poly,NULL);

gtk_tree_store_set(tree_store,&top_poly,

0,"Polygons",-1);

gtk_tree_store_append(tree_store,&other,NULL);

gtk_tree_store_set(tree_store,&other,

0,"Others",-1);

return GTK_TREE_MODEL(tree_store);

}

/*获得文本输入框内容,并将其加入到树视图中显示,并隐藏新建文件窗口

* 输入参数:按钮构件本身button,包含文本输入框、树视图和绘图区的结构体wv

* 输出参数:无

* 日期:2007-4-7修改*/

void get_new_file(GtkWidget *button,wview *wv)

{

char *str=malloc(20*sizeof(char));

str=(char*)gtk_entry_get_text(GTK_ENTRY(wv->entry));

GtkTreeIter child;

gtk_tree_store_append(tree_store,&child,&other);/*向树存储类型的构件中添加条目*/

gtk_tree_store_set(tree_store,&child, /*设置新添加条目的文本显示*/

0,str,-1);

/*FILE *fp=NULL;

if((fp=fopen(str,"w"))==NULL)

printf("error in open file %s\n",str);

fclose(fp);*/

gtk_widget_hide(wv->window);

}

/*隐藏窗口,

* 输入参数:按钮button,窗口构件window

* 输出参数:无

* 日期:2007-4-7修改*/

void cancel_create(GtkWidget *button,GtkWidget *window)

{

gtk_widget_hide(window);

}

/*创建文件菜单的回调函数。用于打开一个对话框,让用户输入文件名,然后将文件名放到树视图的other条目下,创建文件,

* 输入参数:菜单项本身create_file_item, 树视图view

* 输出参数:无

* 日期:2007-4-7修改*/

void create_file(GtkWidget *create_file_button,GtkWidget *view)

{

GtkWidget *window,*entry;

GtkWidget *label,*vbox,*hbox,*b_ok,*b_cancel;

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_widget_set_size_request(window,300,110);

gtk_window_set_title(GTK_WINDOW(window),"create part file");

g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_widget_destroy),NULL);

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);

vbox=gtk_vbox_new(FALSE,15);

gtk_container_add(GTK_CONTAINER(window),vbox);

label=gtk_label_new("Please input the file name:");

gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);

entry=gtk_entry_new();

gtk_box_pack_start(GTK_BOX(vbox),entry,FALSE,FALSE,0);

hbox=gtk_hbox_new(FALSE,0);

gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);

wview *wv=malloc(sizeof(wview));

wv->window=window;

wv->view=view;

wv->entry=entry;

b_ok=gtk_button_new_with_label(" ok ");

g_signal_connect(G_OBJECT(b_ok),"clicked",G_CALLBACK(get_new_file),wv);

gtk_box_pack_start(GTK_BOX(hbox),b_ok,FALSE,FALSE,50);

b_cancel=gtk_button_new_with_label("cancel");

g_signal_connect(G_OBJECT(b_cancel),"clicked",G_CALLBACK(cancel_create),window);

gtk_box_pack_start(GTK_BOX(hbox),b_cancel,FALSE,FALSE,50);

gtk_widget_show_all(window);

}

/*用于隐藏构件,这里是将messagebox窗口隐藏,

* 输入参数:按钮本身button,窗口构件data

* 输出参数:无

* 日期:2007-4-7修改*/

void f_button(GtkWidget * button,GtkWidget * data)

{

gtk_widget_hide(data);

}

/*一个消息提示框,弹出一个窗口,用于提示当前的错误或者其它信息

* 输入参数:字符串str

* 输出参数:无

* 日期:2007-4-7修改*/

void messagebox(const char* str)

{

GtkWidget * window,*table,*label,*button;

/////

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),"messagebox");

gtk_widget_set_size_request(GTK_WIDGET(window),300,100);

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);

g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_widget_destroy),NULL);

/////

table=gtk_table_new(2,3,FALSE);

gtk_container_add(GTK_CONTAINER(window),table);

///

label=gtk_label_new(str);

gtk_table_attach_defaults(GTK_TABLE(table),label,1,2,0,1);

gtk_widget_show(label);

button=gtk_button_new_with_label(" 确定 ");

gtk_table_attach(GTK_TABLE(table),button,1,2,1,2,GTK_SHRINK,GTK_FILL,0,0);

g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(f_button),window);

gtk_widget_show(button);

gtk_widget_show_all(window);

}

/*导入文件对话框ok按钮的回调函数,实现读取文件名,并在将文件内容读取到链表结束后,

* 根据图形类型修改树视图和绘图区,将文件名添加到树视图的相应条目下。

* 输出参数:按钮本身:button,包含标签、树视图和绘图区的一个结构体

* 输出参数:无

* 日期:2007-4-7修改*/

void get_import_file(GtkWidget* button,wdview *wdv)

{

char *str=malloc(20*sizeof(char));

str=(char*)gtk_entry_get_text(GTK_ENTRY(wdv->entry));

char *filename=malloc(20*sizeof(char));

sprintf(filename,"%s.124",str);

FILE *fp=NULL;

if((fp=fopen(filename,"r"))==NULL)

{

messagebox("the file you import is not exist !");

return ;

}

char ch;

_2d_point *p=malloc(sizeof(_2d_point));

fscanf(fp,"%c",&ch);

GtkTreeIter child;

if(ch=='P') //判断是哪种类型的部件,以便放到对应目录下

{

gtk_tree_store_append(tree_store,&child,&top_pix);

gtk_tree_store_set(tree_store,&child,

0,str,-1);

draw_type=PIX_DRAW;

}

else if(ch=='L')

{

gtk_tree_store_append(tree_store,&child,&top_line);

gtk_tree_store_set(tree_store,&child,

0,str,-1);

draw_type=LINE_DRAW;

}

else if(ch=='C')

{

gtk_tree_store_append(tree_store,&child,&top_circle);

gtk_tree_store_set(tree_store,&child,

0,str,-1);

draw_type=CIRCLE_DRAW;

}

else if(ch=='R')

{

gtk_tree_store_append(tree_store,&child,&top_rect);

gtk_tree_store_set(tree_store,&child,

0,str,-1);

draw_type=RECT_DRAW;

}

else if(ch=='D')

{

gtk_tree_store_append(tree_store,&child,&top_poly);

gtk_tree_store_set(tree_store,&child,

0,str,-1);

draw_type=POLY_DRAW;

}

else

{

gtk_tree_store_append(tree_store,&child,&other);

gtk_tree_store_set(tree_store,&child,

0,str,-1);

}

GSList *iter1=prt;

while(iter1)//删除数组中原来内容

{

prt=g_slist_remove_link(prt,iter1);

g_slist_free(iter1);

iter1=prt;

}

while(!feof(fp))

{

p=malloc(sizeof(_2d_point));

int ret=fscanf(fp,"%f",&(p->x));

ret=fscanf(fp,"%f",&(p->y));

if(ret!=1)

{

break;

}

prt=g_slist_append(prt,p);

}

draw_prt(wdv->draw_area);

gtk_widget_destroy(wdv->window);

fclose(fp);

}

/*导入菜单的回调函数,创建一个窗口用于输入要导入的文件名,ok按钮的回调函数实现读取文件名,

* 将文件读取到链表,并修改树视图和绘图区的显示,

* 输入参数:菜单项本生import_file_button, 包含树视图和绘图区的结构体td

* 输出参数:无,

* 日期:2007-4-7修改*/

void import_file(GtkWidget *import_file_button,tree_drawing *td)

{

GtkWidget *window,*entry;

GtkWidget *label,*vbox,*hbox,*b_ok,*b_cancel;

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_widget_set_size_request(window,300,110);

gtk_window_set_title(GTK_WINDOW(window),"create part file");

g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_widget_destroy),NULL);

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);

vbox=gtk_vbox_new(FALSE,15);

gtk_container_add(GTK_CONTAINER(window),vbox);

label=gtk_label_new("Please input the file you want to import:");

gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);

entry=gtk_entry_new();

gtk_box_pack_start(GTK_BOX(vbox),entry,FALSE,FALSE,0);

hbox=gtk_hbox_new(FALSE,50);

gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);

wdview *wdv=malloc(sizeof(wdview));

wdv->window=window;

wdv->view=td->tree_view;

wdv->entry=entry;

wdv->draw_area=td->draw_area;

b_ok=gtk_button_new_with_label(" ok ");

g_signal_connect(G_OBJECT(b_ok),"clicked",G_CALLBACK(get_import_file),wdv);

gtk_box_pack_start(GTK_BOX(hbox),b_ok,FALSE,FALSE,50);

b_cancel=gtk_button_new_with_label("cancel");

g_signal_connect(G_OBJECT(b_cancel),"clicked",G_CALLBACK(cancel_create),window);

gtk_box_pack_start(GTK_BOX(hbox),b_cancel,FALSE,FALSE,0);

gtk_widget_show_all(window);

}

/*导出文件的回调函数,根据当前选中的树视图中的项,将链表中的数据写到文本文件中,

* 在文本文件中,第一行是图形的类型,后面的是数据,

* 存储的文件名就是当前选中的那一行的文本。

* 输入参数:菜单项本身export_file, 树视图view

* 输出参数:无

* 日期:2007-4-7修改*/

void export_file(GtkWidget *export_file,GtkWidget *view)

{

GtkTreeIter iter;

GtkTreeView *treeview=(GtkTreeView*)view;

GtkTreeSelection *selection=gtk_tree_view_get_selection(treeview);/*获得树视图的选定行*/

if(gtk_tree_selection_get_selected(selection,NULL,&iter))/*从选定行获得选定项*/

{

gint i;

GtkTreePath *path;

path=gtk_tree_model_get_path(model,&iter); /*由选定项获得路径。这条在这里无用*/

//i=gtk_tree_path_get_indeces(path)[0];

// gtk_tree_store_set (tree_store, &iter, column,

// filename, -1);

//获得文本

char *text=malloc(sizeof(char));

gtk_tree_model_get(GTK_TREE_MODEL(tree_store),&iter,0,&text,-1);/*由项获得项的文本*/

char *file_name=malloc(19*sizeof(char));

sprintf(file_name,"%s.124",text);

FILE *fp=NULL;

if((fp=fopen(file_name,"w"))==NULL)

{

messagebox("conn't open file you saved!");

return ;

}

GSList *iterator=prt;

char type;

if(draw_type==PIX_DRAW)

{

type='P';

}

else if(draw_type==LINE_DRAW)

{

type='L';

}

else if(draw_type==CIRCLE_DRAW)

{

type='C';

}

else if(draw_type==RECT_DRAW)

{

type='R';

}

else if(draw_type==POLY_DRAW)

{

type='D';

}

else

{

messagebox("you have not create file!");

return ;

}

fprintf(fp,"%c\n",type);

while(iterator)

{

fprintf(fp,"%f\t%f\n",((_2d_point*)(iterator->data))->x,((_2d_point*)(iterator->data))->y);

iterator=iterator->next;

}

fclose(fp);

}

return;

}

/*绘图函数,根据width和height的值将链表中的数据进行变换到当前坐标系下,由draw_type决定绘制什么图形,

* 输入参数:绘图区data,

* 输出参数:无

* 日期:2007-4-7*/

void draw_prt(GtkWidget *data)

{

int area_w=100,area_h=100;

area_w=data->allocation.width; //获得窗口尺寸

area_h=data->allocation.height;

gdk_window_clear(data->window);

GSList *iter1=NULL,*iter2=NULL;

iter1=prt;

if(iter1==NULL){

return ;

}

iter2=prt->next;

if(draw_type==PIX_DRAW)

{

int x,y;

while(iter1)

{

x=(((_2d_point*)(iter1->data))->x)*area_w/width+area_w/2;

y=(((_2d_point*)(iter1->data))->y)*area_h/height+area_h/2;

gdk_draw_point(GTK_WIDGET(data)->window,GTK_WIDGET(data)->style->

fg_gc[GTK_WIDGET_STATE (data)],x,y);

iter1=iter1->next;

}

}

if(draw_type==LINE_DRAW)

{

int x0,x1,y0,y1;

while(iter2)

{

x0=(((_2d_point*)(iter1->data))->x)*area_w/width+area_w/2;

y0=(((_2d_point*)(iter1->data))->y)*area_h/height+area_h/2;

x1=(((_2d_point*)(iter2->data))->x)*area_w/width+area_w/2;

y1=(((_2d_point*)(iter2->data))->y)*area_h/height+area_h/2;

gdk_draw_line(GTK_WIDGET(data)->window,GTK_WIDGET(data)->

style->fg_gc[GTK_WIDGET_STATE (data)],x0,y0,x1,y1);

iter1=iter2;

iter2=iter1->next;

}

}

if(draw_type==CIRCLE_DRAW)

{

int x0,x1,y0,y1;

int r=0.0;

while(iter1&&iter2)

{

x0=(((_2d_point*)(iter1->data))->x)*area_w/width+area_w/2;

y0=(((_2d_point*)(iter1->data))->y)*area_h/height+area_h/2;

x1=(((_2d_point*)(iter2->data))->x)*area_w/width+area_w/2;

y1=(((_2d_point*)(iter2->data))->y)*area_h/height+area_h/2;

r=sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));

gdk_draw_arc(GTK_WIDGET(data)->window,GTK_WIDGET(data)->style->

fg_gc[GTK_WIDGET_STATE (data)],FALSE,x0-r,y0-r,2*r,2*r,0,64*360);

iter1=iter2->next;

if(iter1)

{

iter2=iter1->next;

}

}

}

if(draw_type==RECT_DRAW)

{

int x0,x1,y0,y1;

while(iter1&&iter2)

{

x0=(((_2d_point*)(iter1->data))->x)*area_w/width+area_w/2;

y0=(((_2d_point*)(iter1->data))->y)*area_h/height+area_h/2;

x1=(((_2d_point*)(iter2->data))->x)*area_w/width+area_w/2;

y1=(((_2d_point*)(iter2->data))->y)*area_h/height+area_h/2;

int h=abs(y1-y0);

int w=abs(x1-x0);

x0=x0<x1?x0:x1;

y0=y0<y1?y0:y1;

gdk_draw_rectangle(GTK_WIDGET(data)->window,GTK_WIDGET(data)->style->

fg_gc[GTK_WIDGET_STATE (data)],FALSE,x0,y0,w,h);

iter1=iter2->next;

if(iter1)

{

iter2=iter1->next;

}

}

}

if(draw_type==POLY_DRAW)

{

int x0,x1,y0,y1;

while(iter2)

{

x0=(((_2d_point*)(iter1->data))->x)*area_w/width+area_w/2;

y0=(((_2d_point*)(iter1->data))->y)*area_h/height+area_h/2;

x1=(((_2d_point*)(iter2->data))->x)*area_w/width+area_w/2;

y1=(((_2d_point*)(iter2->data))->y)*area_h/height+area_h/2;

gdk_draw_line(GTK_WIDGET(data)->window,GTK_WIDGET(data)->style->

fg_gc[GTK_WIDGET_STATE (data)],x0,y0,x1,y1);

iter1=iter2;

iter2=iter1->next;

}

x0=(((_2d_point*)(iter1->data))->x)*area_w/width+area_w/2;

y0=(((_2d_point*)(iter1->data))->y)*area_h/height+area_h/2;

x1=(((_2d_point*)(prt->data))->x)*area_w/width+area_w/2;

y1=(((_2d_point*)(prt->data))->y)*area_h/height+area_h/2;

gdk_draw_line(GTK_WIDGET(data)->window,GTK_WIDGET(data)->style->

fg_gc[GTK_WIDGET_STATE (data)],x0,y0,x1,y1);

}

}

/*工具栏上放大按钮的回调函数,实现将对象放大显示(通过将全局变量width和height的值改变,并修改绘图区显示),

* 输入参数:工具栏按钮本身enlarge和绘图区构件data,

* 输出参数:无,

* 日期:2007-4-7修改*/

void enlarge_obj(GtkWidget *enlarge,GtkWidget *data)

{

width=width/1.2;

height=height/1.2;

draw_prt(data);

}

/*工具栏上缩小按钮的回调函数,实现将对象缩小显示(通过将全局变量width和height的值改变,并修改绘图区显示),

* 输入参数:工具栏按钮本身deflate和绘图区构件data,

* 输出参数:无,

* 日期:2007-4-7修改*/

void deflate_obj(GtkWidget *deflate,GtkWidget *data)

{

width=width*1.2;

height=height*1.2;

draw_prt(data);

}

/*菜单Draw下的Plygon菜单项的回调函数,实现将全局变量draw_type属性为点,并将存放数据信息的链表清空。

* 输入参数:无

* 输出参数:无

* 时间:2007-4-7修改*/

void draw_pix(void)

{

//清空绘图区

//设置图象类型

GSList *iter1=prt;

while(iter1)

{

prt=g_slist_remove_link(prt,iter1);

g_slist_free(iter1);

iter1=prt;

}

draw_type=PIX_DRAW;

}

/*菜单Draw下的Plygon菜单项的回调函数,实现将全局变量draw_type属性为线,并将存放数据信息的链表清空。

* 输入参数:无

* 输出参数:无

* 时间:2007-4-7修改*/

void draw_line(void)

{

// 清空绘图区

GSList *iter1=prt;

while(iter1)

{

prt=g_slist_remove_link(prt,iter1);

g_slist_free(iter1);

iter1=prt;

}

draw_type=LINE_DRAW;

}

/*菜单Draw下的Plygon菜单项的回调函数,实现将全局变量draw_type属性为圆,并将存放数据信息的链表清空。

* 输入参数:无

* 输出参数:无

* 时间:2007-4-7修改*/

void draw_circle(void)

{

//

GSList *iter1=prt;

while(iter1)

{

prt=g_slist_remove_link(prt,iter1);

g_slist_free(iter1);

iter1=prt;

}

draw_type=CIRCLE_DRAW;

}

/*菜单Draw下的Plygon菜单项的回调函数,实现将全局变量draw_type属性为矩形,并将存放数据信息的链表清空。

* 输入参数:无

* 输出参数:无

* 时间:2007-4-7修改*/

void draw_rect(void)

{

//

GSList *iter1=prt;

while(iter1)

{

prt=g_slist_remove_link(prt,iter1);

g_slist_free(iter1);

iter1=prt;

}

draw_type=RECT_DRAW;

}

/*菜单Draw下的Plygon菜单项的回调函数,实现将全局变量draw_type属性为多边形,并将存放数据信息的链表清空。

* 输入参数:无

* 输出参数:无

* 时间:2007-4-7修改*/

void draw_poly(void)

{

//

GSList *iter1=prt;

while(iter1)

{

prt=g_slist_remove_link(prt,iter1);

g_slist_free(iter1);

iter1=prt;

}

draw_type=POLY_DRAW;

}

/*创建File菜单

* 输入参数:包含树视图和绘图区的结构体td,

* 输出参数:菜单项file_item,

* 日期:2007-4-7修改*/

GtkWidget* create_file_item(tree_drawing *td)

{

GtkWidget *file_menu; //定义菜单

GtkWidget *file_item;

GtkWidget *new_file,*import_item,*export_item,*quit_item; //file 菜单下的菜单项

char *path=malloc(100*sizeof(char));

//-------------------创建file菜单----------------------------------

file_menu=gtk_menu_new(); //创建菜单

/* 创建菜单项 */

new_file=gtk_menu_item_new_with_label("New");

import_item = gtk_menu_item_new_with_label ("Import");

export_item = gtk_menu_item_new_with_label ("Export");

quit_item = gtk_menu_item_new_with_label ("Quit");

/* 将它们加到菜单中 */

gtk_menu_append(GTK_MENU(file_menu),new_file);

gtk_menu_append (GTK_MENU (file_menu),import_item);

gtk_menu_append (GTK_MENU (file_menu),export_item);

gtk_menu_append (GTK_MENU (file_menu),quit_item);

/* 将回调函数绑定到activate信号 */

g_signal_connect_swapped(G_OBJECT(new_file),"activate",G_CALLBACK(create_file),td->tree_view);

g_signal_connect_swapped (G_OBJECT (import_item), "activate",G_CALLBACK (import_file),td);

g_signal_connect_swapped (G_OBJECT (export_item), "activate", G_CALLBACK (export_file),td->tree_view);

g_signal_connect_swapped (G_OBJECT (quit_item), "activate",G_CALLBACK (gtk_main_quit),NULL);

file_item = gtk_menu_item_new_with_label ("File");

//gtk_widget_set_size_request(GTK_WIDGET(file_item),50,20);

gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);

return file_item;

}

/*创建菜单Draw

* 输入参数:无

* 输出参数:菜单项:draw_menu

* 日期:2007-4-7修改*/

GtkWidget* create_draw_item(void)

{

GtkWidget *draw_menu; //定义菜单

GtkWidget *draw_item;

GtkWidget *circle_draw,*rect_draw,*polygon_draw,*line_draw,*pixel_draw;

draw_menu=gtk_menu_new();

pixel_draw=gtk_menu_item_new_with_label("Pixel");

line_draw=gtk_menu_item_new_with_label("Line");

circle_draw=gtk_menu_item_new_with_label("Circle");

rect_draw=gtk_menu_item_new_with_label("Rectangle");

polygon_draw=gtk_menu_item_new_with_label("Polygon");

gtk_menu_append(GTK_MENU(draw_menu),pixel_draw);

gtk_menu_append(GTK_MENU(draw_menu),line_draw);

gtk_menu_append(GTK_MENU(draw_menu),circle_draw);

gtk_menu_append(GTK_MENU(draw_menu),rect_draw);

gtk_menu_append(GTK_MENU(draw_menu),polygon_draw);

g_signal_connect_swapped(G_OBJECT(pixel_draw),"activate",G_CALLBACK(draw_pix),NULL);

g_signal_connect_swapped(G_OBJECT(line_draw),"activate",G_CALLBACK(draw_line),NULL);

g_signal_connect_swapped(G_OBJECT(circle_draw),"activate",G_CALLBACK(draw_circle),NULL);

g_signal_connect_swapped(G_OBJECT(rect_draw),"activate",G_CALLBACK(draw_rect),NULL);

g_signal_connect_swapped(G_OBJECT(polygon_draw),"activate",G_CALLBACK(draw_poly),NULL);

draw_item=gtk_menu_item_new_with_label("Draw");

//gtk_widget_set_size_request(GTK_WIDGET(draw_item),50,20);

gtk_menu_item_set_submenu(GTK_MENU_ITEM(draw_item),draw_menu);

return draw_item;

}

/*创建工具栏,由于在工具栏中的按钮的回调函数需要修改树视图和绘图区,

* 所以将树视图和绘图区作为参数传递进来,以便回调函数参数传递

* 输入参数:包含绘图区和树视图的结构体td

* 输出参数:工具栏构件handlebox

* 时间:2007-4-7修改*/

GtkWidget* create_toolbar(tree_drawing *td)

{

GtkWidget *handlebox;

GtkWidget *toolbar;

GtkWidget *new_button,*import_button,*export_button,*quit_button;//工具按钮

GtkWidget *zoom_out,*zoom_in;

GtkWidget * iconw;

handlebox=gtk_handle_box_new();

toolbar=gtk_toolbar_new(); //设置工具栏格式

gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);

gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);

gtk_container_set_border_width (GTK_CONTAINER (toolbar), 5);

new_button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"New","Create a file","Private",NULL,GTK_SIGNAL_FUNC(create_file),td->tree_view);

import_button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"Import",

"Import file","Private",NULL,GTK_SIGNAL_FUNC(import_file),td);

export_button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"Export",

"Export file","Private",NULL,GTK_SIGNAL_FUNC(export_file),td->tree_view);

iconw=gtk_image_new_from_file("enlarge.png");

zoom_out=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),NULL,"zoom out","Private",iconw,GTK_SIGNAL_FUNC(enlarge_obj),td->draw_area);

gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));

iconw=gtk_image_new_from_file("deflate.png");

zoom_in=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),NULL,"zoom in","Private",iconw,GTK_SIGNAL_FUNC(deflate_obj),td->draw_area);

quit_button=gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"Quit",

"Quit the file","Private",NULL,GTK_SIGNAL_FUNC(gtk_main_quit),NULL);

gtk_container_add(GTK_CONTAINER(handlebox),toolbar);

return handlebox;

}

/*在绘图区中点击鼠标事件的回调函数,

* 如果点击左键则按照绘图类型将鼠标处的坐标值处理后添加到链表prt中,并调用显示函数,显示图形;

* 如果是鼠标右键,则将绘图类型设置为FALSE

* 输入参数:事件盒构件本身event_box,事件:event,绘图区构件:data

* 输出参数:TURE活FALSE,这个暂时没实际意义

* 时间:2007-4-7修改*/

static gboolean button_press_callback(GtkWidget *event_box,GdkEventButton *event,GtkWidget *data)

{

if(!draw_type)

{

return FALSE;

}

/*

if(event->button==2)

{

gtk_menu_popup()

}

*/

if(event->button==3)

{

draw_type=FALSE;

}

int area_w=100,area_h=100;

area_w=data->allocation.width; //获得窗口尺寸

area_h=data->allocation.height;

if(event->button==1)

{

_2d_point *p=malloc(sizeof(_2d_point));

p->x=((event->x-area_w/2)*width/area_w);

p->y=((event->y-area_h/2)*height/area_h);

prt=g_slist_append(prt,p);

//printf("%f %f\t,%d,%d\n",p->x,p->y,area_w,area_h);

GSList *iter1=NULL,*iter2=NULL;

iter1=prt;

iter2=prt->next;

gdk_draw_point(GTK_WIDGET(data)->window,GTK_WIDGET(data)->style->

fg_gc[GTK_WIDGET_STATE (event_box)],event->x,event->y);

draw_prt(data);

}

//gdk_drawable_unref(GTK_WIDGET(data)->window);

return TRUE;

}

/*

static gboolean view_press(GtkWidget *widget,GdkEventButton *event,GtkWidget *menu)

{

if(event->button==3)

{

gtk_menu_popup(GTK_MENU(widget),NULL,NULL,NULL,NULL,event->button,event->time);

}

}*/

static gboolean

expose_event(GtkWidget *widget, GdkEventExpose *event,gpointer data)

{

draw_prt(widget);

return TRUE;

}

gint main(gint argc,char *argv[])

{

GtkWidget *window;

GtkWidget *file_item,*draw_item; /*菜单项*/

GtkWidget *menu_bar; /*菜单*/

GtkWidget *tool_bar; /*工具栏*/

GtkWidget *vbox,*hpaned; /*竖直盒,水平分栏窗口*/

GtkWidget *view,*event_box,*draw_area;

GtkWidget *handle_box; /*手柄构建,用于存放工具按钮*/

gtk_init(&argc,&argv);

window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_title(GTK_WINDOW(window),"drawing window");

g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);

gtk_widget_set_size_request(GTK_WIDGET(window),500,400);

gtk_container_set_border_width (GTK_CONTAINER (window), 10);

vbox = gtk_vbox_new (FALSE, 0); /*创建主竖直盒*/

gtk_container_add (GTK_CONTAINER (window), vbox);

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);/*将窗口的显示位置设定为屏幕中央*/

draw_area=gtk_drawing_area_new();/*由于这两个构件需要作为其它构件回调函数的参数,所以先在这里创建*/

view=(GtkWidget*)create_tree();

tree_drawing *td=malloc(sizeof(tree_drawing));/*定义结构体,以便回调函数调用*/

td->tree_view=view;

td->draw_area=draw_area;

/*======================== 添加菜单 ===================================== */

menu_bar = gtk_menu_bar_new ();

gtk_box_pack_start(GTK_BOX(vbox),menu_bar,FALSE,FALSE,3);

file_item=create_file_item(td); //调用自定义创建菜单file的函数

gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);

draw_item=create_draw_item();

gtk_menu_bar_append(GTK_MENU_BAR(menu_bar),draw_item);

/*

GtkWidget *pop_up;

pop_up=pop_menu(draw_area);

*/

/*========================= 添加工具栏 =================================*/

handle_box=create_toolbar(td); /*调用自定义函数创建工具栏,由于工具栏中的按钮需要改变绘图区和树视图,所以需要将绘图区和树视图作为参数进行传递*/

gtk_box_pack_start(GTK_BOX(vbox),handle_box,FALSE,FALSE,3);

/*========================= 添加树视图 ==========================================*/

hpaned=gtk_hpaned_new(); /*创建水平分栏窗口*/

gtk_box_pack_start(GTK_BOX(vbox),hpaned,TRUE,TRUE,3);

//g_signal_connect_swapped(G_OBJECT(view),"event",G_CALLBACK(view_press),pop_up);//添加右键菜单

gtk_paned_add1(GTK_PANED(hpaned),view);

/*========================== 添加绘图区 =========================================*/

event_box=gtk_event_box_new(); //添加eventbox以便鼠标响应

gtk_paned_add2(GTK_PANED(hpaned),event_box);

gtk_container_add(GTK_CONTAINER(event_box),draw_area);

/*-----------test - color------*/

GdkColor color;

color.red=55000;

color.blue=55000;

color.green=55000;

gtk_widget_modify_bg(draw_area,GTK_STATE_NORMAL,&color); /*设置背景颜色*/

GdkColor colorf;

colorf.red=0;

colorf.blue=65535;

colorf.green=0;

gtk_widget_modify_fg(draw_area,GTK_STATE_NORMAL,&colorf); /*设置前景颜色*/

g_signal_connect(G_OBJECT(event_box),"button_press_event",G_CALLBACK(button_press_callback),draw_area);

g_signal_connect(G_OBJECT(draw_area),"expose_event",G_CALLBACK(expose_event),NULL);

//-----------------------------

gtk_widget_show_all(window);

width=draw_area->allocation.width; /*获得绘图区尺寸,并赋值给全局变量width和height*/

height=draw_area->allocation.height;

gtk_main();

return 0;

}

下面是编译命令:

$> gcc -o main `pkg-config --cflags --libs gtk+-2.0 glib-2.0` soft.c

编译完成之后将图标enlarge.png

和deflate.png

拷贝到同一目录下即可执行了。界面如下:



关于使用方面的这里介绍一点,打开后,点击菜单Draw,然后选中对应类型就可以在绘图区绘制了,也可以导入对象,导入文件的格式全部为.124格式( :),自己随便定义的格式),若想保存,应该首先新建,然后绘制,绘制完毕之后,选中树视图中的对象名,点击export工具图标即可导出,导入时只需输入文件名,不需要扩展名(切记),在绘图时不要点击右键,右键将清空绘图。当然了,放大/缩小图标就是用来放大缩小用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: