Gtk::ScrolledWindow と Gtk::EventBox の順番
概要
Gtk::Image などの "no window" ウィジットでイベントを取得するにはGtk::EventBoxに貼る(add)必要が あるが、さらに Gtk::ScrolledWindow と組み合わせるときにウィジットを貼る順番を間違えると一部の イベントが正常に取得できないことがある。例えばGtk::Image -> Gtk::EventBox -> Gtk::ScrolledWindow の順に貼っても、 Gtk::Image -> Gtk::ScrolledWindow -> Gtk::EventBox の順に貼っても表示は同じであるが、 後者の場合はマウスのボタンを押しながらのmotion_notifyイベントを取得できない。
従って正しくイベントを取得するには "no window" ウィジット -> Gtk::EventBox -> Gtk::ScrolledWindow の 順に貼る必要がある。
ソース
eventscr.cpp (わざとマウスボタンを押しながらのmotion_notifyイベントを取得出来ないようにしてある)#include <gtkmm.h> #include <iostream> class MainWin : public Gtk::Window { Gtk::Image m_img; Gtk::ScrolledWindow m_scr; Gtk::EventBox m_event; public: MainWin(); private: bool slot_motion_notify_event( GdkEventMotion* event ){ std::cout << "motion\n"; } }; MainWin::MainWin() : m_img( "./test.png" ) { m_event.add_events( Gdk::POINTER_MOTION_MASK ); m_event.signal_motion_notify_event() .connect( sigc::mem_fun( *this, &MainWin::slot_motion_notify_event ) ); m_scr.add( m_img ); m_event.add( m_scr ); add( m_event ); show_all_children(); } int main( int argc, char *argv[] ) { Gtk::Main kit( argc, argv ); MainWin mainwin; Gtk::Main::run( mainwin ); return 0; }
コンパイル
必要なコンパイルオプションは pkg-config を使って取得する。g++ eventscr.cpp -o eventscr `pkg-config gtkmm-2.4 --cflags --libs`
結果
上のコードではマウスボタンを押さないときにマウスを動かすと "motion" という文字が表示されるが、 マウスボタンを押しながらマウスを動かすと何も表示されない。そこでMainWin()を次のように変更する。MainWin::MainWin() : m_img( "./test.png" ) { m_event.add_events( Gdk::POINTER_MOTION_MASK ); m_event.signal_motion_notify_event() .connect( sigc::mem_fun( *this, &MainWin::slot_motion_notify_event ) ); m_event.add( m_img ); m_scr.add( m_event ); add( m_scr ); show_all_children(); }Widgetをaddする順番に注意。今度はマウスボタンを押しながらマウスを動かしたときでも"motion"と表示される。