根据鼠标的进入/离开事件来打开和关闭小部件的焦点

问题描述

我想在鼠标指针进入此小部件时打开Gtk::SpinButton条目焦点,然后在指针离开时再次将其关闭。

当窗口仍在运行时,信号事件似乎没有响应。但是在我关闭窗口后,将输出std::cout输出。

如何实现预期的小部件行为?

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

class SpinButtonExample : public Gtk::Window {
    Gtk::Grid                     grid;
    Gtk::Label                    label;
    Glib::RefPtr<Gtk::Adjustment> adjustment;
    Gtk::SpinButton               spinbutton;

public:
    SpinButtonExample();
    bool on_enter_notify_event(GdkEventCrossing *);
    bool on_leave_notify_event(GdkEventCrossing *);
};

SpinButtonExample::SpinButtonExample()
    : label     ("Hi"),adjustment(Gtk::Adjustment::create(0,10)),spinbutton(adjustment)
{
    add_events(Gdk::ENTER_NOTIFY_MASK);
    add_events(Gdk::LEAVE_NOTIFY_MASK);

    spinbutton.signal_enter_notify_event().connect(
                sigc::mem_fun(*this,&SpinButtonExample::on_enter_notify_event));
    spinbutton.signal_leave_notify_event().connect(
                sigc::mem_fun(*this,&SpinButtonExample::on_leave_notify_event));

    grid.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
    grid.set_column_homogeneous(true);
    grid.set_margin_start(10);
    grid.set_margin_end(10);
    grid.set_margin_top(10);
    grid.set_margin_bottom(10);
    grid.add(label);
    grid.add(spinbutton);

    add(grid);

    show_all();
}

bool
SpinButtonExample::on_enter_notify_event(GdkEventCrossing *event)
{
    if (event->type == GDK_SCROLL) {
        std::cout << "Mouse entered\n";
        spinbutton.set_can_focus();
        return true;
    }
    return false;
}

bool
SpinButtonExample::on_leave_notify_event(GdkEventCrossing *event)
{
    if (event->type == GDK_LEAVE_NOTIFY) {
        std::cout << "Mouse left\n";
        spinbutton.set_can_focus(false);
        return true;
    }
    return false;
}

int
main()
{
    auto application = Gtk::Application::create("test.focus.spinbutton");

    SpinButtonExample test;

    return application->run(test);
}

解决方法

非常感谢underscore_d的上述评论。

此问题的答案是,当鼠标指针离开Gtk::SpinButton小部件时将我们的焦点移至另一个小部件,并为enter事件获取焦点。

仅使用set_can_focus()进行打开和关闭将无法正常工作。

下面是更正的解决方案:

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

class SpinButtonExample : public Gtk::Window {
    Gtk::Grid                     grid;
    Gtk::Label                    label;
    Glib::RefPtr<Gtk::Adjustment> adjustment;
    Gtk::SpinButton               spinbutton;
    Gtk::Button                   button;

public:
    SpinButtonExample();
    bool on_enter_notify_event(GdkEventCrossing *);
    bool on_leave_notify_event(GdkEventCrossing *);
};

SpinButtonExample::SpinButtonExample()
    : label     ("Hi"),adjustment(Gtk::Adjustment::create(0,10)),spinbutton(adjustment),button    ("Default")
{
    add_events(Gdk::ENTER_NOTIFY_MASK);
    add_events(Gdk::LEAVE_NOTIFY_MASK);

    button.set_margin_start(10);
    button.set_can_default();
    button.grab_focus();

    spinbutton.set_can_default(false);
    spinbutton.signal_enter_notify_event().connect(
                sigc::mem_fun(*this,&SpinButtonExample::on_enter_notify_event));
    spinbutton.signal_leave_notify_event().connect(
                sigc::mem_fun(*this,&SpinButtonExample::on_leave_notify_event));

    grid.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
    grid.set_column_homogeneous(true);
    grid.set_margin_start(10);
    grid.set_margin_end(10);
    grid.set_margin_top(10);
    grid.set_margin_bottom(10);
    grid.add(label);
    grid.add(spinbutton);
    grid.add(button);

    add(grid);

    show_all();
}

bool
SpinButtonExample::on_enter_notify_event(GdkEventCrossing *event)
{
    if (event->type == GDK_ENTER_NOTIFY) {
        std::cout << "Mouse entered" << std::endl;
        spinbutton.grab_focus();
        return true;
    }
    return false;
}

bool
SpinButtonExample::on_leave_notify_event(GdkEventCrossing *event)
{
    if (event->type == GDK_LEAVE_NOTIFY) {
        std::cout << "Mouse left" << std::endl;
        button.grab_focus();
        return true;
    }
    return false;
}

int
main()
{
    auto application = Gtk::Application::create("test.focus.spinbutton");

    SpinButtonExample test;

    return application->run(test);
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...