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

GTKmm 4中TreeView关联Popover Menu时菜单项无悬停高亮问题

解决GTKmm 4中TreeView绑定PopoverMenu时菜单项悬停不高亮的问题

我之前也碰到过一模一样的问题,这本质是TreeView的事件处理机制和Popover的事件传递冲突了——虽然菜单项的点击动作能触发,但鼠标悬停事件被TreeView拦截了,导致高亮样式无法生效。下面给你两种可行的解决方案:

方案一:将PopoverMenu的父控件改为窗口

当Popover的父控件是TreeView时,TreeView内部的事件处理逻辑会干扰Popover接收鼠标事件。把父控件换成你的窗口实例(Window类对象)就能避开这个问题,只需要调整两处代码:

  1. 修改构造函数中的Popover父控件设置:
// 替换原来的 menu_.set_parent(treeview_);
menu_.set_parent(*this);
  1. 更新on_popup_button_pressed中的坐标转换逻辑,把TreeView的本地坐标转为窗口坐标:
void on_popup_button_pressed(int, double x, double y) {
    int cx, cy;
    treeview_.convert_widget_to_bin_window_coords(x, y, cx, cy);
    Gtk::TreeModel::Path path;
    treeview_.get_path_at_pos(cx, cy, path);
    if (!path) {
        return;
    }

    // 将TreeView的坐标转换为窗口坐标(Popover的父控件坐标)
    int win_x, win_y;
    treeview_.translate_coordinates(*this, x, y, win_x, win_y);
    const Gdk::Rectangle rect(win_x, win_y, 1, 1);
    menu_.set_pointing_to(rect);
    menu_.popup();
}

方案二:抢占GestureClick的事件序列

如果你想保留PopoverMenu作为TreeView的子控件,可以在右键点击时让Gesture抢占事件,阻止TreeView继续处理这个右键动作,这样Popover就能正常接收鼠标悬停事件了:

  1. 先修改信号连接代码,把Gesture指针传递到处理函数中:
gesture->signal_pressed().connect(sigc::bind(sigc::mem_fun(*this, &Window::on_popup_button_pressed), gesture));
  1. 更新处理函数的签名和逻辑,在开头抢占事件:
void on_popup_button_pressed(Glib::RefPtr<Gtk::GestureClick> gesture, int, double x, double y) {
    // 标记事件为已处理,阻止TreeView继续响应右键点击
    gesture->set_state(Gtk::EventSequenceState::CLAIMED);

    int cx, cy;
    treeview_.convert_widget_to_bin_window_coords(x, y, cx, cy);
    Gtk::TreeModel::Path path;
    treeview_.get_path_at_pos(cx, cy, path);
    if (!path) {
        return;
    }
    const Gdk::Rectangle rect(x, y, 1, 1);
    menu_.set_pointing_to(rect);
    menu_.popup();
}

两种方案都能解决菜单项悬停不高亮的问题,你可以根据自己的布局需求选择其中一种。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 20:52:34