c - GDK 线程不允许 gtk 更改(制作计时器)

标签 c multithreading timer gtk gdk

 #include <gtk/gtk.h>
 #include<string.h>
 #include<stdio.h>
 #include <stdbool.h>
 #include<stdlib.h>

 static GtkWidget *textlabel_question_no;
 static GtkWidget *textlabel_answer1;
 static GtkWidget *textlabel_answer2;
 static GtkWidget *textlabel_answer3;
 static GtkWidget *textlabel_answer4;
 static GtkWidget *textlabel_question;
 static GtkWidget *textlabel_timer;
 static GtkWidget *textlabel_timeleft;
 static GtkWidget *button_next;
 static GtkWidget *window2;
 static GtkWidget *window31;
 static GThread  *thread;

 void show_info(GtkWidget *window2);

 // thread for timer
 static gpointer thread_Func(gpointer data)
 {

  // gdk_threads_enter();
int min=0,sec;//min=29

while(min > -1 )
{
    sec = 10;
    while(sec>=0)
    {
       sleep(1);
      char* timer_text=malloc(sizeof(char)*40);
      if(sec>9)
      {
        sprintf(timer_text,"%d : %d",min,sec);
      }
      else
      {
        sprintf(timer_text,"%d : 0%d",min,sec);
      }
      gtk_label_set_text(GTK_LABEL(textlabel_timer),timer_text);
      sec--;
    }
    min--;
    }
   // gdk_threads_leave();

    // gdk_threads_enter();
      g_printf("in show_info\n");
      GtkWidget *dialog;
      dialog = gtk_message_dialog_new(GTK_WINDOW(window2),
                     GTK_DIALOG_DESTROY_WITH_PARENT,
                     GTK_MESSAGE_INFO,
                     GTK_BUTTONS_OK,
             "Your Time is UP !!!\n Lets see the Result & Statistics...","title");                         
         gtk_window_set_title(GTK_WINDOW(dialog), "Time Finished");
         gint result=gtk_dialog_run(GTK_DIALOG(dialog));

         switch(result)
            {
              case GTK_RESPONSE_OK:
              gtk_widget_hide(window2);
             g_printf("in show_info\n");

            system("./result &");
            //gtk_main_quit();
            break;
           }
          //sleep(10);
       gtk_widget_destroy(dialog);


     /*
     window31 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
     gtk_window_set_position(GTK_WINDOW(window31), GTK_WIN_POS_CENTER);
     gtk_window_set_title(GTK_WINDOW(window31), "Examination Panel");
     gtk_container_set_border_width(GTK_CONTAINER(window31),12);
     gtk_window_set_resizable(GTK_WINDOW(window31),FALSE);
     gtk_widget_set_size_request(window31,300,150);
     gtk_widget_show_all(window31);
     //sleep(10);
      gdk_threads_leave();*/
     return NULL;
   }

    static void next_question_label_change(GtkWidget *button_next,gpointer data)
     { 
     g_printf("in button_next\n");
     static int question_value=2;
     char *question_label = malloc(sizeof(char)*50);
     sprintf(question_label,"Question %d of 10.",question_value);
     gtk_label_set_text(GTK_LABEL(textlabel_question_no),question_label);
     if(question_value<10)
       question_value++;
   }



     //For Submit button dialog box
     static void test_submit_window(GtkWidget *button_next,GtkWidget *window2)
     {
       GtkWidget *dialog;
       dialog = gtk_message_dialog_new(GTK_WINDOW(window2),
                 GTK_DIALOG_DESTROY_WITH_PARENT,
                 GTK_MESSAGE_QUESTION,
                 GTK_BUTTONS_YES_NO,
                 "Are you sure to Submit the Test?");

     gtk_window_set_title(GTK_WINDOW(dialog), "Submit Test Confirmation");
     gint result = gtk_dialog_run (GTK_DIALOG (dialog));


     switch(result)
      {
      case GTK_RESPONSE_YES:

      system("./result &");
      gtk_widget_hide(window2);
            break;
      case GTK_RESPONSE_NO:
      break;
      }
     gtk_widget_destroy(dialog);

   }

     int
    main (int argc,char *argv[])
    {   

     GTimer *g_time;

     GtkWidget *fixed;
     GtkWidget *radio1,*radio2,*radio3,*radio4;
     GtkWidget *button_submit;
     GtkWidget *textlabel_title;
     GtkWidget *image;
     GtkWidget *image2;
     GError *error = NULL;
     GdkPixbuf *pixbuf;  
     GtkWidget *scrolled_window;


     /* Secure glib */
      if( ! g_thread_supported() )
    g_thread_init( NULL );

     //g_threads_init(NULL);
      //g_thread_init(NULL);
      /* Secure gtk */
      gdk_threads_init();

      /* Obtain gtk's global lock */



    // intialiazation
     gtk_init (&argc, &argv);




     //window attributes position,size,title
     window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
     gtk_window_set_position(GTK_WINDOW(window2), GTK_WIN_POS_CENTER);
     gtk_window_set_title(GTK_WINDOW(window2), "Examination Panel");
     gtk_container_set_border_width(GTK_CONTAINER(window2),12);
     gtk_window_set_resizable(GTK_WINDOW(window2),FALSE);
     gtk_widget_set_size_request(window2,800,450);

     button_next = gtk_button_new_with_label("Next>>");
     button_submit = gtk_button_new_with_label("Submit");

     textlabel_title = gtk_label_new("-> TECHNICAL EXAM <-");
     textlabel_question = gtk_label_new("question placed here");
     textlabel_question_no = gtk_label_new(" Question 1 of 10.");
     textlabel_answer1 = gtk_label_new(" answer 1");
     textlabel_answer2 = gtk_label_new(" answer 2");
     textlabel_answer3 = gtk_label_new(" answer 3");
     textlabel_answer4 = gtk_label_new(" answer 4");
     textlabel_timer =   gtk_label_new("30:00");
     textlabel_timeleft = gtk_label_new("Time Left  :");



     //radio button for option
    radio1 =  gtk_radio_button_new_with_label (NULL , "A. ");
    radio2 =  gtk_radio_button_new_with_label_from_widget
            (GTK_RADIO_BUTTON(radio1),"B.");                         
     radio3 = gtk_radio_button_new_with_label_from_widget
             (GTK_RADIO_BUTTON (radio1),"C. ");
     radio4 = gtk_radio_button_new_with_label_from_widget
              (GTK_RADIO_BUTTON (radio1),"D. ");


  // For image
     pixbuf = gdk_pixbuf_new_from_file_at_size 
             ("/home/trilok/trantorlogo.png", 100,  100, &error);
   if(!pixbuf)
    {
   g_print ("Error: %s\n",error->message);
    g_error_free (error);
  /* Handle error here */
  }
  image = gtk_image_new_from_pixbuf(pixbuf);
  image2 = gtk_image_new_from_pixbuf(pixbuf);
  g_object_unref (pixbuf);




 //For Signals
 g_signal_connect (window2, "destroy", G_CALLBACK (gtk_main_quit), NULL);
 g_signal_connect (button_next,"clicked",G_CALLBACK
            (next_question_label_change), NULL);
 g_signal_connect (button_submit,"clicked",G_CALLBACK(test_submit_window),window2);


 //timer

 // pthread_create(&pth,NULL,threadFunc,"foo");
 /* Create new thread */
  thread = g_thread_create( thread_Func,NULL,
                          FALSE,&error);
  if( ! thread )
  {
    g_print( "Error: %s\n", error->message );
    return( -1 );
  }


  // For scrolled window 
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_container_set_border_width (GTK_CONTAINER (scrolled_window),10);
   gtk_scrolled_window_set_policy 
         (GTK_SCROLLED_WINDOW     
           (scrolled_window)
        ,GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);


   //fixed
   fixed = gtk_fixed_new();
   gtk_container_add(GTK_CONTAINER(window2), fixed);
  gtk_widget_show(fixed);
  gtk_scrolled_window_add_with_viewport
             (GTK_SCROLLED_WINDOW(scrolled_window),textlabel_question);
  gtk_widget_set_size_request(scrolled_window,580,150);


 //scrolled border
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
                   GTK_SHADOW_IN);
  gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolled_window),
                 GTK_CORNER_TOP_LEFT);




  gtk_fixed_put(GTK_FIXED(fixed), scrolled_window, 70, 110);
  gtk_fixed_put(GTK_FIXED(fixed), image, 0, 0);
  gtk_fixed_put(GTK_FIXED(fixed), image2, 0, 510);
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_title, 300, 20);
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_timeleft, 610, 70);  
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_timer, 690, 70);  
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_question_no, 65, 70);  
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer1,170, 300);
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer2,170, 350);
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer3,170, 400);
  gtk_fixed_put(GTK_FIXED(fixed), textlabel_answer4,170, 450);
  gtk_fixed_put(GTK_FIXED(fixed), radio1, 100,300);
  gtk_fixed_put(GTK_FIXED(fixed), radio2, 100,350);
  gtk_fixed_put(GTK_FIXED(fixed), radio3, 100,400);
  gtk_fixed_put(GTK_FIXED(fixed), radio4, 100,450);
  gtk_fixed_put(GTK_FIXED(fixed), button_next,620, 500);
  gtk_fixed_put(GTK_FIXED(fixed), button_submit,690, 500);
  gtk_widget_show_all(window2);


   //gdk_threads_enter();
   GDK_THREADS_ENTER();
    gtk_main();

   /* Release gtk's global lock */
   //gdk_threads_leave();
    GDK_THREADS_LEAVE();

 return 0;
 }

实际上我正在考试模拟器上制作一个计时器。我的计时器工作正常,但问题是当计时器转到 0:00 时我必须打开一个对话框。我已经实现了线程来制作计时器。问题是,当计时器转到 0:00 时,就会出现段错误。 gdk 线程不允许对 gtk 小部件进行任何调用。

感谢您提前提供的帮助。 如果有人纠正上面的代码并使其实现,我们将不胜感激

最佳答案

  1. 不清楚您是否使用了 gdk_threads_enter(),因为有一堆注释掉的调用和一个宏。 GTK+ 不是线程安全的,您尝试的方法不是正确的方法。
  2. 您确实不需要为此使用线程,只需使用 glib 计时器即可。
  3. 您正在从 timer_text 分配中泄漏内存; gtk_label_set_text() 不会转移文本缓冲区的所有权(请注意,它是 const)。

关于c - GDK 线程不允许 gtk 更改(制作计时器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18831168/

相关文章:

c++ - ADT规范

c - 为什么 Valgrind 提示的是 printf 而不是我未初始化的计数器?

java - JTable 复选框应在选中时启动计时器

java - 使用 JavaFX 中的计时器平移场景的矩形

c - 在 openGL 中构造一条线

c - 程序内存泄漏? C

multithreading - Tomcat:如何避免每个 session 线程

c++ - 无法将接口(interface)从主线程编码到工作线程

java - 两个线程使用同一对象但修改该对象的单独属性

c# - Timer_Tick() + this.ActiveControl 导致 TextReader() 崩溃?