【问题标题】:GTK+ - How to listen to an event from within a method?GTK+ - 如何从方法中监听事件?
【发布时间】:2011-12-11 06:56:24
【问题描述】:

我正在编写一个运行算法的应用程序,但允许您通过按下按钮“逐步执行”算法 - 显示每一步发生的情况。

如何在方法中侦听事件? 例如,看看我得到的代码。

static int proceed; 

button1Event(GtkWidget *widget)
{
    proceed = 0;

    int i = 0; 
    for (i=0; i<15; i++)  //this is our example 'algorithm'
    {

                    while (proceed ==0) continue; 

        printf("the nunmber is %d\n", i);
        proceed = 0; 

    }


}

button2Event(GtkWidget *widget)
{
    proceed = 1; 

}

这不起作用,因为它需要退出 button1 方法才能侦听 button2(或任何其他事件)。

我正在考虑类似的 while 循环。

 while(proceed == 0)
 {
    listen_for_button_click(); 
 }

那是什么方法?

【问题讨论】:

    标签: events event-handling gtk


    【解决方案1】:

    这里的“真正”答案(任何有经验的 GTK+ 程序员都会给你的答案)可能不是你会喜欢的:不要这样做,你的代码结构错误。

    选项包括:

    • 建议:将应用程序重组为事件驱动;可能您需要跟踪您的状态(状态机或布尔标志)并忽略当前不适用的按钮。
    • 您可以运行递归主循环,就像在另一个答案中使用 gtk_main_iteration();然而,这是非常危险的,因为任何 UI 事件都可能在该循环中发生,例如关闭窗口或其他完全不相关的事情。不适用于任何大小的大多数实际应用。
    • 将阻塞逻辑移至另一个线程,并通过 GAsyncQueue 或类似的方式进行通信(注意,这很难做到正确,而且可能会过度杀伤)。

    我认为你在这里出错了:

     while(proceed == 0)
     {
        listen_for_button_click(); 
     }
    

    你不想要这样的 while 循环;您只希望 GTK+ 主循环执行您的阻塞。当您单击按钮时,在它的回调中,然后编写此 while 循环之后的任何代码。

    【讨论】:

    • 对。我在reddit thread 中给出的建议是 button1 事件应该只初始化一个结构,button2 事件在运行算法时使用它来跟踪它的位置。
    • +1 回答得很好!这是开发人员提出的常见设计“要求”。在回调中循环通常不是一个好主意。尽管 gtk_main_iteration 用于这种情况。嗯,不太确定如何处理其他 不相关 事件是危险的,因为如果用户关闭窗口,那么他/她希望它会关闭,如果您可以增加一点清晰度,那就太好了!
    • 在一个大型程序中,您可能有很多窗口,其中一些与您正在做的事情无关,还有 IO 操作和计时器以及在您的事件循环中运行的其他类型的东西。因此,在事件循环中阻塞的任何地方,都必须处理可能发生的任何事情;例如,它可以免费或修改您正在使用的数据结构。递归事件循环也完全阻止 gtk_main_quit(或 g_main_loop_quit)退出程序。递归主循环是对未知的其他概念“线程”的合作让步;没有锁定。不安全。
    【解决方案2】:

    您可以在单击的回调中检查未决事件并处理 while 循环中的事件。这些方面的内容:

    button1Event(GtkWidget *widget)
    {
        proceed = 0;
    
        int i = 0; 
        for (i=0; i<15; i++)  //this is our example 'algorithm'
        {
    
           while (proceed ==0)
           {
               /* Check for all pending events */
               while(gtk_events_pending())
               {
                    gtk_main_iteration(); /* Handle the events */    
               }
               continue; 
           }
    
            printf("the nunmber is %d\n", i);
            proceed = 0; 
    
        }
    
    }
    

    这样,当与第二个按钮的点击相关的事件被添加到要处理的事件队列中时,检查会将事件视为待处理并处理它们然后继续。通过这种方式,您的全局价值变化可以得到反映,并且应该可以进行步进。
    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      如果您想这样做,我想到的唯一方法是为您的算法创建一个单独的线程,并使用一些同步方法从按钮单击处理程序中通知该线程。

      GTK+(更具体地说,glib)有自己的API 用于线程和同步。据我所知Condition variables 是实现等待通知逻辑的标准方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-22
        • 2021-06-07
        • 2019-10-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-16
        • 2011-10-20
        • 1970-01-01
        相关资源
        最近更新 更多