簡単な描画ツールを作成2(オフスクリーン使用)
概要
簡単な描画ツールを作成する。今回はオフスクリーンを使用する前回作ったツールはウィンドウを切り替えるなどして再描画を行うと 画像が消えていた。そこで今回はオフスクリーンを使用して再描画を 行っても画像が消えないようにする。
オフスクリーンとしてGdk::Pixmapを使用する。Gdk::Pixmapは Gdk::Windowと同じくGdk::Drawableのサブクラスであるから描画系のメンバ 関数を使用して画像を描くことが出来る。オフスクリーンに描いた画像は on_expose_event()でdraw_drawable()を使って表のスクリーンにコピーする。 またオフスクリーンに描画したらqueue_draw()によって再描画を行う。 それ以外は基本的に前回とほとんど変わらない。
ソース
drawpic2.cpp#include <gtkmm.h> class MyDrawArea : public Gtk::DrawingArea { Glib::RefPtr< Gdk::Pixmap > m_pixmap; Glib::RefPtr< Gdk::GC > m_gc; // ポインタの以前の座標 int m_pre_x; int m_pre_y; public: MyDrawArea(); private: void draw_line( int x1, int y1, int x2, int y2 ); protected: virtual void on_realize(); bool on_expose_event( GdkEventExpose* event ); virtual bool on_button_press_event( GdkEventButton* event ); virtual bool on_motion_notify_event( GdkEventMotion* event ); }; MyDrawArea::MyDrawArea() { // OFFになってるイベントを追加 add_events( Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK ); } void MyDrawArea::on_realize() { // 元のon_realize()へのコールを忘れないこと Gtk::DrawingArea::on_realize(); // オフスクリーン作成 m_pixmap = Gdk::Pixmap::create( get_window(), get_width(), get_height() ); m_gc = Gdk::GC::create( m_pixmap ); // 背景を白く塗りつぶし int width = get_width(); int height = get_height(); m_gc->set_rgb_fg_color( Gdk::Color( "white" ) ); m_pixmap->draw_rectangle( m_gc, true, 0, 0, width, height ); } bool MyDrawArea::on_expose_event( GdkEventExpose* event ) { // オフスクリーンから画像をコピーするだけなのでデフォルトのGCを使う get_window()->draw_drawable( get_style()->get_fg_gc( get_state() ), m_pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height ); return true; } // 線を引く void MyDrawArea::draw_line( int x1, int y1, int x2, int y2 ) { m_gc->set_rgb_fg_color( Gdk::Color( "red" ) ); m_gc->set_line_attributes( 4, Gdk::LINE_SOLID, Gdk::CAP_ROUND, Gdk::JOIN_ROUND ); m_pixmap->draw_line( m_gc, x1, y1, x2, y2 ); // 再描画依頼 queue_draw(); } // マウスクリック bool MyDrawArea::on_button_press_event( GdkEventButton* event ) { m_pre_x = (int)event->x; m_pre_y = (int)event->y; draw_line( m_pre_x, m_pre_y, m_pre_x, m_pre_y ); return true; } // マウスをドラッグした bool MyDrawArea::on_motion_notify_event( GdkEventMotion* event ) { if( event->state == Gdk::BUTTON1_MASK ){ int x2 = (int)event->x; int y2 = (int)event->y; draw_line( m_pre_x, m_pre_y, x2, y2 ); m_pre_x = x2; m_pre_y = y2; } return true; } class MainWin : public Gtk::Window { MyDrawArea m_drawarea; public: MainWin(){ resize( 400, 400 ); add( m_drawarea ); 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++ drawpic2.cpp -o drawpic2 `pkg-config gtkmm-2.4 --cflags --libs`