问题描述
我想在鼠标指针进入此小部件时打开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);
}