2016-06-18 9 views
0

私は作物の選択のために、このコードを使用します。gtk cで "gdk_pixbuf_composite"の選択図形マーカーを変更するには?

croppic = gdk_pixbuf_new_from_file("E:/Works for Gov Project/DOC/GUI/logogui1/crop_bg.png", NULL); 

img1 = gtk_image_new(); 
event_box = gtk_event_box_new(); 
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), FALSE); 
gtk_container_add(GTK_CONTAINER(event_box), img1); 
gtk_container_add(GTK_CONTAINER(frame1), event_box); 

g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(mouse_press_callback), NULL); 
g_signal_connect(G_OBJECT(event_box), "button-release-event", G_CALLBACK(mouse_press_callback), NULL); 

と "crop_bg.png" は次のとおりです:メイン機能であること

gboolean mouse_press_callback(GtkWidget  *event_box, 
           GdkEventButton *event, 
           gpointer  data) 
{ 
    if (img1buffer == NULL) 
     return TRUE; 

    static gint press_x = 0, press_y = 0, rel_x = 0, rel_y = 0; 

    GtkAllocation ebox; 
    gint img1_x_offset = 0, img1_y_offset = 0; 
    gtk_widget_get_allocation(event_box, &ebox); 
    img1_x_offset = (ebox.width - width)/2; 
    img1_y_offset = (ebox.height - height)/2; 

    if (event->type == GDK_BUTTON_PRESS) 
    { 
     press_x = event->x - img1_x_offset; 
     press_y = event->y - img1_y_offset; 
     //g_print ("Event box clicked at coordinates %f,%f\n", 
     //event->x - img1_x_offset, event->y - img1_y_offset); 
    } 
    else if (event->type == GDK_BUTTON_RELEASE) 
    { 
     rel_x = event->x - img1_x_offset; 
     rel_y = event->y - img1_y_offset; 
     //g_print ("Event box released at coordinates %f,%f\n", 
     //event->x - img1_x_offset, event->y - img1_y_offset); 

     dest_x = rel_x < press_x ? rel_x : press_x; 
     dest_y = rel_y < press_y ? rel_y : press_y; 
     dest_width = abs(rel_x - press_x); 
     dest_height = abs(rel_y - press_y); 

     // mark user selection in image 
     GdkPixbuf *img1buffer_resized = gdk_pixbuf_scale_simple(img1buffer, width, height, GDK_INTERP_TILES); 
     gdk_pixbuf_composite(croppic, img1buffer_resized, dest_x, dest_y, dest_width, dest_height, 0, 0, 1, 1, GDK_INTERP_TILES, 170); 
     gtk_image_set_from_pixbuf(GTK_IMAGE(img1), img1buffer_resized); 
    } 

    return TRUE; 
} 

enter image description here

しかし、私がしたいですペイントソフトウェアと同様の選択形状:

enter image description here

このタスクを解決する方法については、どのようなアイデアをお考えですか?または、インターネット上のどのリソースでヘルプを見つけることができますか?

+0

だから、gtk3またはgtk2ですか?その答えは、両者では大きく異なります。 – andlabs

+0

@ andlabs、gtk3にあります。 –

+0

これでGDKコンポジションを使用する必要はありません。代わりに、cairoを使用して ':: draw'をオーバーライドします。そのような破線の長方形を作成することができます。私が答えを投稿する前に、私が何を意味するのか理解していますか? – andlabs

答えて

1

GtkImageの上に描画しようとしています。これはカスタム図面を作成する最良の方法ではありません。気づいたように、gdk_pixbuf_composite()はかなり限定されています。

代わりに::drawシグナルとcairoを使用して、図表the proper wayを実行します。カイロはGTK + 3は、独自のウィジェットを描画するために使用し、::draw信号はあなたに描画するカイロのコンテキストを与えるベクトルグラフィックスライブラリです:

gboolean draw(GtkWidget *widget, cairo_t *cr, void *data); 

カイロ自体は使いやすいです。それはwell documentedであり、a whole bunch of samplesです。あなたの目的のために何をしたいのかは、破線の矩形を描いています。

さらに、GtkImageを使用する代わりに、GtkDrawingAreaを使用します。 GtkDrawingAreaは特に描画されるように設計されており、イベントを処理するために余分な作業を加えることができます。

パズルの最後の部分は、マウスイベントが入ったときに描画を開始する方法です。 button-press-eventまたはbutton-release-eventcairo_tが含まれていないため、そこに描画することはできません。 GTK +は最適化されているので、必要なときだけ描画されます。描画する必要があることを示すには、gtk_widget_queue_draw()メソッドを使用します。このメソッドには、再描画するウィジェットのサブセットのみをマークするバリエーションがあります(::drawハンドラ内からcairo_clip_extents()でこのサブセットを戻すことができます)。

ウィジェットの座標は浮動小数点です。カイロの座標もそうです。

このためにグローバル変数を使用します。あなたはおそらくしたくないでしょう。

gdouble x0, y0; 
gdouble x1, y1; 

これらは、長方形の端点を格納します。我々は、マウスのボタンを押したとき、私たちは、描画を開始したい:

gboolean button_press_event(GtkWidget *widget, GdkEventButton *e, gpointer data) 
{ 
    // ... 
    x0 = e->x; 
    y0 = e->y; 
    x1 = e->x; // start with a zero-sized rectangle 
    y1 = e->y; 
    // ... 
} 

我々は、マウスを移動すると、私たちは、新しいマウスの座標にx1y1を変更し、矩形を更新します。あなたはおそらく上からbutton-release-eventに何をすべきかを把握することができます

gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *e, gpointer data) 
{ 
    // ... 
    // first queue both old and new rectangles for drawing 
    gtk_widget_queue_draw_area(widget, 
     x0, y0, 
     MAX(x1, e->x), MAX(y1, e->y)); 
    // then set the new rectangle 
    x1 = e->x; 
    y1 = e->y; 
    // ... 
} 

:物事を最適化するために、我々は唯一の変更エリアを更新します。draw

gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data) 
{ 
    // ... 
    cairo_rectangle(cr, x0, y0, x1 - x0, y1 - y0); 
    // set up a dashed solid-color stroke 
    cairo_stroke(cr); 
    // ... 
} 

幸運のようになります!

+0

@ andlabs:あなたの投稿には本当にありがとうございます。私は私の質問を編集し、それの終わりにC++コードを追加します。しかし、私はあなたの新しい関数でmain関数内の "gboolean mouse_press_callback"関数とC++ codをどのように変更し改善するのか分かりません。 –

関連する問題