GTKmm 4中TreeView关联Popover Menu时菜单项无悬停高亮问题
我之前也碰到过一模一样的问题,这本质是TreeView的事件处理机制和Popover的事件传递冲突了——虽然菜单项的点击动作能触发,但鼠标悬停事件被TreeView拦截了,导致高亮样式无法生效。下面给你两种可行的解决方案:
方案一:将PopoverMenu的父控件改为窗口
当Popover的父控件是TreeView时,TreeView内部的事件处理逻辑会干扰Popover接收鼠标事件。把父控件换成你的窗口实例(Window类对象)就能避开这个问题,只需要调整两处代码:
- 修改构造函数中的Popover父控件设置:
// 替换原来的 menu_.set_parent(treeview_); menu_.set_parent(*this);
- 更新
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就能正常接收鼠标悬停事件了:
- 先修改信号连接代码,把Gesture指针传递到处理函数中:
gesture->signal_pressed().connect(sigc::bind(sigc::mem_fun(*this, &Window::on_popup_button_pressed), gesture));
- 更新处理函数的签名和逻辑,在开头抢占事件:
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
相关产品推荐
相关产品推荐

