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

如何在Gtkmm中持续检测Gtk::Calendar选中日期的变化?

实现Gtk::Calendar选中日期变化的事件监听与事件排序

嗨,我来帮你搞定这个需求!其实你完全不需要写后台持续检测的逻辑——GTK本身就是事件驱动的框架,Gtk::Calendar自带了专门的信号来监听选中日期的变化,用这个比后台轮询高效太多了。

下面是具体的实现步骤和代码示例:

核心思路:利用GTK的信号机制

Gtk::Calendar提供了day_selected信号,每当用户选中新的日期(不管是点击日期、切换月份还是年份),这个信号就会自动触发。我们只需要把这个信号和自定义的回调函数绑定,在回调里完成日期获取和事件排序的操作就行。

完整代码示例

#include <gtkmm.h>
#include <vector>
#include <iostream>

class MyWindow : public Gtk::Window {
public:
    MyWindow() {
        // 设置窗口布局(用水平Box放置日历和列表)
        set_title("日期事件管理器");
        set_default_size(600, 400);
        m_main_box.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
        add(m_main_box);

        // 初始化日历组件
        m_main_box.pack_start(m_calendar, Gtk::PACK_SHRINK);

        // 初始化列表存储与树视图
        m_event_columns.add(m_col_name);
        m_event_columns.add(m_col_deadline);
        m_list_store = Gtk::ListStore::create(m_event_columns);
        m_tree_view.set_model(m_list_store);
        m_tree_view.append_column("事件名称", m_col_name);
        m_tree_view.append_column("截止日期", m_col_deadline);
        m_main_box.pack_start(m_tree_view, Gtk::PACK_EXPAND_WIDGET);

        // 绑定日历的日期选中信号到回调函数
        m_calendar.signal_day_selected().connect(
            sigc::mem_fun(*this, &MyWindow::on_date_selected_changed)
        );

        // 模拟添加一些测试事件
        add_test_events();
        show_all_children();
    }

private:
    // 定义列表存储的列结构
    class EventColumns : public Gtk::TreeModel::ColumnRecord {
    public:
        EventColumns() { add(name); add(deadline); }
        Gtk::TreeModelColumn<Glib::ustring> name;
        Gtk::TreeModelColumn<Glib::Date> deadline; // 用Glib::Date做精确日期比较
    };

    EventColumns m_event_columns;
    Gtk::TreeModelColumn<Glib::ustring> m_col_name = m_event_columns.name;
    Gtk::TreeModelColumn<Glib::Date> m_col_deadline = m_event_columns.deadline;

    Gtk::Box m_main_box;
    Gtk::Calendar m_calendar;
    Glib::RefPtr<Gtk::ListStore> m_list_store;
    Gtk::TreeView m_tree_view;
    std::vector<std::pair<Glib::ustring, Glib::Date>> m_all_events; // 存储所有事件的数据源

    // 添加测试事件
    void add_test_events() {
        Glib::Date date1(20, 5, 2024); // 日、月、年(月份从1开始)
        Glib::Date date2(21, 5, 2024);
        Glib::Date date3(21, 5, 2024);
        m_all_events.emplace_back("完成项目报告", date1);
        m_all_events.emplace_back("部门周会", date2);
        m_all_events.emplace_back("提交代码版本", date3);
    }

    // 日期变化时的回调函数
    void on_date_selected_changed() {
        // 获取当前选中的日期
        unsigned int year, month, day;
        m_calendar.get_date(year, month, day);
        // 注意:GTK的calendar.get_date返回的月份是从0开始的,需要转成1-based
        Glib::Date selected_date(day, month + 1, year);

        // 对事件进行筛选+排序:筛选出截止日期等于选中日期的事件,按名称排序
        m_list_store->clear();
        for (const auto& event : m_all_events) {
            if (event.second == selected_date) {
                Gtk::TreeModel::Row row = *(m_list_store->append());
                row[m_col_name] = event.first;
                row[m_col_deadline] = event.second;
            }
        }

        // 如果需要更复杂的排序(比如按截止日期远近),可以用TreeModelSort
        // auto sort_model = Gtk::TreeModelSort::create(m_list_store);
        // sort_model->set_sort_func(m_col_deadline, sigc::ptr_fun(sort_by_deadline));
        // m_tree_view.set_model(sort_model);
    }

    // 可选:自定义排序函数示例
    static int sort_by_deadline(const Gtk::TreeModel::iterator& a, const Gtk::TreeModel::iterator& b) {
        Glib::Date date_a, date_b;
        *a >> date_a;
        *b >> date_b;
        return date_a.compare(date_b);
    }
};

int main(int argc, char* argv[]) {
    auto app = Gtk::Application::create(argc, argv, "org.example.calendar_event_sorter");
    MyWindow window;
    return app->run(window);
}

关键细节说明

  • 信号选择:除了day_selected,还有month_changed(切换月份时触发)、day_selected_double_clicked(双击日期触发)等信号,可根据需求灵活选用。
  • 日期处理:示例中用Glib::Date存储截止日期,相比字符串能更精准地进行日期比较,避免格式不一致的问题。
  • 排序优化:如果事件数量较多,建议使用Gtk::TreeModelSort来实现内置排序,无需手动清空列表再重新添加,性能更优。

这样一来,每当用户改变日历的选中日期,回调函数就会自动执行,完成事件的筛选或排序操作,完全不需要后台循环检测,既高效又符合GTK的设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:12:34