LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1054|回复: 3

gtk怎么在子线程中实现对话框?

[复制链接]
发表于 2010-5-30 21:09:16 | 显示全部楼层 |阅读模式
最近我在做一个类似飞鸽的东西,使用gtk,前期虽然很乱,但是还都写过去了。但是这两天有几点很迷茫,希望大家指教一下。

在文件的传输部分出了问题:
我是使用回调函数,在回调函数中加入文件发送函数来实现文件发送方的,例如文件选择对话框,和一个选项对话框,这些都可以正常工作。

对于文件接收方,我使用一个子线程来进行等待文件传输的连接,当accept成功时,就说明有连接到达。这时就使用对话框来选择是够接受该文件,可是该对话框经常无法正常显示,或者就是有段错误,甚至说是x11 server的问题。。。。。
我想了很久,觉得应该是子线程中实现对话框的问题,而我的gtk_main在主线程中实现?不知道我的想法对不?希望各位多多指教。。。。。

全部代码如下
在发送方点完发送之后,在接受方就会出问题

下面是出问题的代码
这时接受方的代码:
。。。
pthread_create(&wait_tid,NULL,file_wait,NULL);
。。。
//这是等待函数
void * file_wait(void * arg)
{
        。。。。。。。。。。。。
                /****************确认是够接受文件************/
                GtkWidget * confirm_dialog;
                printf("\n confirm_dialog new");
                GtkWidget * confirm_label;
                printf("\n confirm_label new");
                char confirm_buf[25];
                printf("\n before dialog new");
                confirm_dialog=gtk_dialog_new_with_buttons(NULL,NULL,GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,NULL);
                sprintf(confirm_buf,"是否接受来自%s的文件?",inet_ntoa(accept_addr.sin_addr));
                confirm_label=gtk_label_new(confirm_buf);
                gtk_container_add(GTK_CONTAINER(GTK_DIALOG(confirm_dialog)->vbox),confirm_label);
                //不能使用一下的方式,否则gtk_dialog_run的结果就是-1,GTK_RESPONSE_NONE
//                g_signal_connect(G_OBJECT(confirm_dialog),"response",G_CALLBACK(gtk_widget_destroy),confirm_dialog);
                gtk_widget_show_all(confirm_dialog);
                int res=1;
                if(GTK_RESPONSE_ACCEPT==gtk_dialog_run(GTK_DIALOG(confirm_dialog))){
                        write(wait_accept_fd,&res,sizeof(res));
                }else{
                        res=-1;
                        write(wait_accept_fd,&res,sizeof(res));
                        gtk_widget_destroy(confirm_dialog);                       
                        continue;
                       
                }
                gtk_widget_destroy(confirm_dialog);
                /************************************************/       
       
                /****************存储路径选择对话***************/
                GtkWidget * file_dialog;
                file_dialog=gtk_file_chooser_dialog_new("选择存储目录",NULL,GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,NULL);
                if(gtk_dialog_run(GTK_DIALOG(file_dialog))==GTK_RESPONSE_ACCEPT){
                        char * folder_name;
                        folder_name=gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(file_dialog));
                        strcpy(path_to_store,folder_name);
                        g_free(folder_name);       
                }else{
                        strcpy(path_to_store,".");
                }
                gtk_widget_destroy(file_dialog);
                /**********************************************/
。。。。。。。。。。。。。。。。。。
        }
}

这时发送方的代码,所有对话框都可以正常出现
//这个函数是发送文件button的回调函数
void file_send_handle(GtkWidget * button,gpointer data)
{
        。。。。
       
        file_send_init(ip);
        g_free(ip);
}

//发送方函数
//功能:文件发送初始化函数
//参数:发送方的目的地址
void file_send_init(char * ip)
{
        。。。。。。。。

        /**************************************/

        /**************************************/
        read(command_fd,buf,20);
        if(*((int *)buf)!=1){       
                GtkWidget * message_dialog;
                message_dialog=gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_INFO,GTK_BUTTONS_CLOSE,"对不起,对方不接受文件");
                g_signal_connect(G_OBJECT(message_dialog),"response",G_CALLBACK(gtk_widget_destroy),message_dialog);
                return;
        }
        /***************************************/

        /*****************文件选择************************/
        GtkWidget * file_dialog;
        file_dialog=gtk_file_chooser_dialog_new("选择发送文件",NULL,GTK_FILE_CHOOSER_ACTION_OPEN,GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,NULL);
//        由于在response信号之后,仍要对dialog进行操作,所以不可以使用信号机制毁掉dialog
//        g_signal_connect(G_OBJECT(file_dialog),"response",G_CALLBACK(gtk_widget_destroy),file_dialog);
        if(gtk_dialog_run(GTK_DIALOG(file_dialog))==GTK_RESPONSE_ACCEPT){
                char * file_name;
                file_name=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
                strcpy(path_to_store,file_name);
                g_free(file_name);
        }else{
                gtk_widget_destroy(file_dialog);
                return;
        }
        gtk_widget_destroy(file_dialog);
        /******************获取文件大小**************************/
        send_file_size=0;
        int file_fd=open(path_to_store,O_RDONLY);
        struct stat stat_buf;
        fstat(file_fd,&stat_buf);
        send_file_size=stat_buf.st_size;
        close(file_fd);
        /******************选项选择***************************/
        GtkWidget * option_dialog;
        GtkWidget * vbox;
        option_dialog=gtk_dialog_new_with_buttons("发送选项",NULL,GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,NULL);
        vbox=gtk_dialog_get_content_area(GTK_DIALOG(option_dialog));
        GtkWidget * hbox;
        GtkWidget * label;       
        hbox=gtk_hbox_new(FALSE,5);
        label=gtk_label_new("文件名称:");
        gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,4);
        label=gtk_label_new(path_to_store);
        gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,4);
        gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,TRUE,4);       
       
        hbox=gtk_hbox_new(FALSE,5);
        label=gtk_label_new("文件大小:");
        gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,4);
        sprintf(buf,"%d",send_file_size);
        label=gtk_label_new(buf);
        gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,4);
        gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,TRUE,4);       

        hbox=gtk_hbox_new(FALSE,5);
        label=gtk_label_new("线程数目:");
        gtk_box_pack_start(GTK_BOX(hbox),label,TRUE,TRUE,4);
        GtkWidget * spin_button=gtk_spin_button_new_with_range(1,10,1);
        gtk_box_pack_start(GTK_BOX(hbox),spin_button,TRUE,TRUE,4);
        gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,TRUE,4);
       
        gtk_widget_show_all(option_dialog);
        if(gtk_dialog_run(GTK_DIALOG(option_dialog))==GTK_RESPONSE_ACCEPT){
                send_file_thread_number=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_button));
                printf("\nsend_file_thread_number : %d ",send_file_thread_number);                       
        }else{
                gtk_widget_destroy(option_dialog);
                return ;
        }       
        gtk_widget_destroy(option_dialog);
        /****************************************************/
        。。。。。。。
       
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2010-5-30 21:30:29 | 显示全部楼层
提示:
GDK_THREADS_ENTER与GDK_THRREADS_LEAVE。
以及gdk_window_process_updates。
回复 支持 反对

使用道具 举报

发表于 2010-6-9 17:47:31 | 显示全部楼层
谢谢分享,真是高手
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-6-9 21:05:02 | 显示全部楼层
Post by realtang;2093367
提示:
GDK_THREADS_ENTER与GDK_THRREADS_LEAVE。
以及gdk_window_process_updates。
谢谢realtang大哥,非常感谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表