You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在GTK4(<4.10)的C语言环境中如何忽略双击并检测单击?

在GTK4中检测单击并忽略双击的解决方案

在Ubuntu 22.04下使用GTK4(4.6)和C语言开发时,若直接监听GtkGestureClick的released信号,双击操作中的第一次点击会被误判为单击。要实现“检测单击、忽略双击时的第一次点击”,核心是通过延迟判断区分单击和双击:

实现思路

  1. 第一次鼠标释放时,启动一个与系统双击间隔时长一致的定时器;
  2. 若超时前未收到第二次点击,触发单击逻辑;
  3. 若收到双击信号,立即取消定时器,忽略本次单击。

代码实现

辅助回调函数

// 定时器回调:执行单击逻辑
gboolean on_single_click_timeout(gpointer user_data) {
    GtkWidget *widget = GTK_WIDGET(user_data);
    
    // 替换为你的单击处理逻辑
    g_print("触发单击事件\n");
    
    // 清除存储的定时器ID
    g_object_set_data(G_OBJECT(widget), "click-timer", NULL);
    return G_SOURCE_REMOVE; // 仅执行一次
}

// 双击信号处理:取消单击定时器
void on_double_clicked(GtkGestureClick *gesture, gint n_press, gdouble x, gdouble y, gpointer user_data) {
    GtkWidget *widget = GTK_WIDGET(user_data);
    guint timer_id = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(widget), "click-timer"));
    
    if (timer_id != 0) {
        g_source_remove(timer_id);
        g_object_set_data(G_OBJECT(widget), "click-timer", NULL);
    }
    
    // 可选:添加双击处理逻辑
    g_print("触发双击事件\n");
}

// 释放信号处理:启动单击定时器
void on_released(GtkGestureClick *gesture, gint n_press, gdouble x, gdouble y, gpointer user_data) {
    GtkWidget *widget = GTK_WIDGET(user_data);
    
    // 获取系统默认双击间隔时间
    GtkSettings *settings = gtk_settings_get_default();
    guint double_click_time;
    g_object_get(settings, "double-click-time", &double_click_time, NULL);
    
    // 启动定时器,延迟执行单击逻辑
    guint timer_id = g_timeout_add(double_click_time, on_single_click_timeout, widget);
    // 将定时器ID绑定到widget,方便后续取消
    g_object_set_data(G_OBJECT(widget), "click-timer", GUINT_TO_POINTER(timer_id));
}

手势控制器初始化

GtkGesture *controller;
controller = gtk_gesture_click_new();
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(controller), 0); // 响应所有鼠标按钮
gtk_gesture_single_set_exclusive(GTK_GESTURE_SINGLE(controller), TRUE);
gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER(controller), GTK_PHASE_CAPTURE);

// 连接信号:释放时启动定时器,双击时取消定时器
g_signal_connect(controller, "released", G_CALLBACK(on_released), myWidget);
g_signal_connect(controller, "double-clicked", G_CALLBACK(on_double_clicked), myWidget);

gtk_widget_add_controller(GTK_WIDGET(myWidget), GTK_EVENT_CONTROLLER(controller));

关键说明

  • 系统双击间隔:通过GtkSettings获取系统配置的双击时间,保证逻辑与系统行为一致,避免硬编码延迟值;
  • 定时器管理:用g_object_set_data将定时器ID绑定到目标widget,无需全局变量,双击触发时及时终止定时器;
  • 信号顺序:double-clicked信号会在第二次点击的released信号之前触发,确保能及时取消第一次点击的定时器。

内容的提问来源于stack exchange,提问作者fmb1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:45:05