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

GTK C++调用g_timeout_add_seconds出现void表达式无效错误如何解决

问题原因

你遇到的编译报错和逻辑问题来自三个核心错误:

  • g_timeout_add_seconds第二个参数要求传入函数指针,你直接调用this->Label(i)相当于把函数执行后的返回值(void)传进去了,自然触发invalid use of void expression报错。
  • C++类的非静态成员函数默认隐含this指针作为第一个参数,和GSourceFunc要求的gboolean (*)(gpointer)签名不兼容,无法直接作为回调传入。
  • 你循环注册10个1秒定时器的逻辑错误,所有定时器会几乎同时在1秒后触发,完全达不到逐秒倒计时的效果。
修复方案

1. 调整类定义,新增必要成员

在Msgbox类的头文件中新增如下声明:

class Msgbox {
// 原有类成员保持不变...
private:
    int m_remaining_sec; // 存储剩余倒计时秒数
    guint m_timer_id; // 存储定时器ID,方便后续提前销毁
    static gboolean timeout_callback(gpointer user_data); // 静态回调函数,符合GSourceFunc签名要求
    void update_label(); // 调整后的标签更新函数
};

2. 重写倒计时逻辑和回调实现

void Msgbox::LabelUpdate(void)
{
    m_remaining_sec = 10;
    // 注册1秒定时器,传入当前实例指针作为用户数据
    m_timer_id = g_timeout_add_seconds(1, timeout_callback, (gpointer)this);
    gtk_widget_set_sensitive(close_btn , TRUE);
    gtk_widget_grab_focus(close_btn);
}

// 静态回调函数,无隐含this参数,可直接作为C风格函数指针传入
gboolean Msgbox::timeout_callback(gpointer user_data)
{
    Msgbox* instance = static_cast<Msgbox*>(user_data);
    instance->m_remaining_sec--;
    instance->update_label();

    if (instance->m_remaining_sec <= 0) {
        // 倒计时结束,关闭窗口,返回G_SOURCE_REMOVE销毁当前定时器
        gtk_widget_destroy(instance->your_window_widget); // 替换为你实际的窗口实例变量名
        return G_SOURCE_REMOVE;
    }
    // 返回G_SOURCE_CONTINUE让定时器继续下一次触发
    return G_SOURCE_CONTINUE;
}

void Msgbox::update_label()
{
    char buf[256];
    sprintf(buf, "<span color=\"purple\"><b> Time to wait : %d secs </b></span>", m_remaining_sec);
    gtk_label_set_markup (GTK_LABEL(msg_lbl), buf);
}

3. 可选优化

如果窗口可能在倒计时结束前被用户手动关闭,需要在窗口销毁的回调中调用g_source_remove(m_timer_id)提前销毁定时器,避免野指针访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:06:00