【问题标题】:Turn widget's focus on and off based on mouse enter/leave event根据鼠标进入/离开事件打开和关闭小部件的焦点
【发布时间】:2020-10-26 10:26:39
【问题描述】:

我想在鼠标指针进入这个小部件时打开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, 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);
}

【问题讨论】:

  • 如果您将std::endl 放在您的couts 中会怎样?即是否只是 cout 没有刷新让您认为事件被延迟到进程结束。
  • 如果你想在进入时打开焦点,你为什么要检查if (event-&gt;type == GDK_SCROLL)?显然,指针输入和滚动是不同的东西。但是您也不必费心检查,因为获取信号意味着事件具有该类型,否则为什么要为特定类型的事件命名信号...?
  • 感谢@underscore_d std::endl 工作。但是离开通知并没有关闭我的小部件焦点
  • 什么意思?它不会关闭 focusability 吗?和/或它是否离开小部件聚焦
  • 先尝试将焦点返回到其他“默认”小部件,然后。

标签: c++ gtk3 gtkmm3


【解决方案1】:

非常感谢上面 underscore_d 的 cmets。

这个问题的答案是当鼠标指针离开Gtk::SpinButton 小部件时将我们的焦点指向另一个小部件,对于进入事件,将焦点重新抓住。

仅使用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, 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-17
    • 2016-02-20
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 2013-06-21
    相关资源
    最近更新 更多