GUI点击下使用GTK +按钮后变得没有反应 [英] GUI becomes unresponsive after clicking the button using GTK+ in C

查看:239
本文介绍了GUI点击下使用GTK +按钮后变得没有反应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


void display(GtkButton * b, gpointer data)
   {    
      while(1)
        {
          printf("hurrah!");

         }

}


void closeapp(GtkButton * b, gpointer data)
 {
   gtk_main_quit();
 }


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


printf("hello");
GtkBuilder *gtkBuilder;
GtkWidget *window;


gtk_init(&argc,&argv);

gtkBuilder = gtk_builder_new();
gtk_builder_add_from_file(gtkBuilder,"hello_world.glade",NULL);

window = GTK_WIDGET(gtk_builder_get_object(gtkBuilder,"mywindow"));
widg.e1 = GTK_ENTRY( gtk_builder_get_object(gtkBuilder, "entry1" ) );
gtk_builder_connect_signals(gtkBuilder, &widg);
g_object_unref(G_OBJECT(gtkBuilder));
gtk_widget_show(window);


gtk_main();


return 0;

}

当我点击按钮,图形用户界面变得无法响应。该计划应打印乌拉,也应该接受其他(closeapp)响应使用gdk_thread_enter()和gdk_thread_leave()button.I尝试,但它警告说,他们是去precated。
请帮忙!

The GUI becomes unresponsive when I click the button. The program should print 'Hurrah' and also it should accept response for the other(closeapp) button.I tried using gdk_thread_enter() and gdk_thread_leave(), but it gave warning that they are deprecated. Please Help!

推荐答案

显示函数包含阻止无限循环,其中$ P $运行pvents GTK的主循环,因此,处理事件或重新绘制的窗口的内容。 GTK不运行事件处理和UI绘制成一个单独的线程,所以你的不能阻止在code中的主循环。

The display function contains a blocking infinite loop, which prevents the GTK main loop from running, and thus processing events or redrawing the contents of your window. GTK does not run the event handling and UI drawing into a separate thread, so you cannot block the main loop in your code.

您既可以使用一个线程,使用 GTask API;或者你的操作分解成离散模块,并使用主循环以及通过API喜欢的 g_timeout_add 或的 g_idle_add

You either use a thread, using the GTask API; or you break down your operation into discrete blocks, and use the main loop as well, through API like g_timeout_add or g_idle_add.

让我们显示后者的例子,因为它更容易把握。如果我们有一个操作可以被分解成多个迭代,我们可以用一个简单的空闲处理器,就像这样:

Let's show an example of the latter, since it's easier to grasp. If we have an operation that can be broken down into multiple iterations, we can use a simple idle handler, like this:

static GtkWidget *label;
static int counter;

static gboolean
on_idle_count_to_five (gpointer data)
{
  /* Increment the global counter */
  counter += 1;

  char *str = g_strdup_printf ("We are at %d!", counter);

  /* Show the current count */
  gtk_label_set_text (GTK_LABEL (counter_label), str);

  g_free (str);

  /* We got past five, so we remove the idle source */
  if (counter == 5)
    return G_SOURCE_REMOVE;

  /* Otherwise we continue */
  return G_SOURCE_CONTINUE;
}

在空闲处理器递增计数器每次更新标签;如果计数器达到目标值,我们删除了处理程序。为了建立处理程序,我们可以使用:

The idle handler increments a counter and updates a label each time; if the counter reaches the target value, we remove the handler. In order to set up the handler, we can use:

...
counter_label = gtk_label_new ();
gtk_container_add (GTK_CONTAINER (parent), counter_label);
gtk_widget_show (counter_label);

/* Install the idle handler in the main loop */
g_idle_add (on_idle_count_to_five, NULL);

使用GTask是一个比较复杂的,因为在同一个主上下文UI的其余部分内运行空闲和超时处理程序,使用一个单独的线程,当我们需要切换到正确的主背景下,以更新UI

Using GTask is a bit more complex because while the idle and timeout handlers run inside the same main context as the rest of the UI, when using a separate thread we need to switch to the correct main context in order to update the UI.

例如,这是定期更新使用由 GTask 包裹线程UI长时间运行的操作:

For instance, this is a long running operation that periodically updates the UI using a thread wrapped by GTask:

/* Ancillary data structure that we can use to keep state */
struct TaskData {
  GtkWidget *counter_label;
  int count;
}

/* Wrapper function for updating the label; this has to be
 * called in the main context that initialized GTK and is
 * spinning the main loop
 */
static void
update_counter_label (gpointer data_)
{
  struct TaskData *data = data_;

  char *str = g_strdup_printf ("We are at %d!", data->count);

  gtk_label_set_text (GTK_LABEL (data->counter_label), str);
  g_free (str);
}

static void
count_to_five (GTask *task,
               gpointer source_obj,
               gpointer task_data,
               GCancellable *cancellable)
{
  struct TaskData *data = task_data;

  /* Count to five with some sleep in the middle to make this a long
   * running operation
   */
  for (int i = 0; i < 5; i++)
    {
      /* Break if GCancellable.cancel() was called */
      if (g_cancellable_is_cancelled (cancellable))
        {
          g_task_return_new_error (task,
                                   G_IO_ERROR, G_IO_ERROR_CANCELLED,
                                   "Task cancelled");
          return;
        }

      /* Invoke update_counter_label in the default main context,
       * which is the one use by GTK
       */
      g_main_context_invoke (NULL, update_counter_label, data);
      g_usleep (500);
    }

  /* The task has finished */
  g_task_return_boolean (task, TRUE);
}

static void
count_to_five_async (GtkWidget *label,
                     GCancellable *cancellable,
                     GAsyncReadyCallback count_to_five_done,
                     gpointer data)
{
  /* Allocate and initialize the task data */
  struct TaskData *data = g_new (TaskData, 1);
  data->counter_label = label;
  data->count = 0;

  /* Runs the count_to_five() function in a thread, and calls
   * count_to_five_done() when the thread terminates
   */
  GTask *task = g_task_new (label, cancellable, count_to_five_done, data);
  g_task_set_task_data (task, data, g_free);
  g_task_run_in_thread (task, count_to_five);
  g_object_unref (task);
}

这篇关于GUI点击下使用GTK +按钮后变得没有反应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆