2017-09-29 28 views
1

私はGTKで本当に新しいですし、私が念頭に置いているプロジェクトのためにそれを処理する方法を学ぼうとしています。GTK描画時に点滅する

私は、ウィンドウに "Generators"を配置するためのアプリを作ることができました...画面をクリックするたびに、アプリはウィンドウ内にgenを配置し、別のものを準備します配置されています... 問題は、すべてのジェネレータを描画するときにプログラムが点滅することです... 各ジェネレーションは常にそれ自体を再描画する必要があります。これは問題だと思います。私はそれをより速くすることができますか? ... 前もって感謝します!!ここ

// gcc main.c -o main `pkg-config gtk+-3.0 --cflags --libs` 
#include <gtk/gtk.h> 
#include <stdlib.h> 
#include <iostream> 
#include <vector> 

using namespace std; 

class Gen{ 
public: 
    int x; 
    int y; 
    GdkPixbuf *pix; 
    GtkWidget *canvas; 
    bool placed; 

    Gen(GtkWidget *canvas){ 
    this->canvas=canvas; 
    GError *err = NULL; 
    pix = gdk_pixbuf_new_from_file("./Img/gen.png", &err); 
    pix= gdk_pixbuf_scale_simple(pix,50,50, GDK_INTERP_BILINEAR); 
    x=10;y=10; 
    placed=0; 
    } 

    void draw(cairo_t *cr){ 
    gdk_cairo_set_source_pixbuf(cr, pix, x, y); 
    cairo_paint(cr); 
    } 

    void updatePosition(int a, int b){ 
     if(placed==0){ 
     x=a-25; 
     y=b-25; 
     } 
    } 

    void place(){ 
     placed=1; 
    } 

}; 

class Map{ 
public: 
    vector<Gen *> Gens; 
    GtkWidget *window; 
    GtkWidget *canvas; 
    int xPointer,yPointer; 

    Map(GtkWidget *_window, GtkWidget *_canvas){ 
     window=_window; 
     canvas=_canvas; 
    } 

    void draw(){ 
     cairo_t *cr; 
     cr = gdk_cairo_create (gtk_widget_get_window(canvas)); 
     cairo_set_source_rgb(cr, 1, 1, 1); 
     cairo_rectangle(cr, xPointer-35, yPointer-35, 70, 70); 
     cairo_paint(cr); 
     for(vector<Gen *>::const_iterator i=Gens.begin();i!=Gens.end();i++){ 
      (*i)->draw(cr); 
     } 
     cairo_destroy (cr); 
    } 
    void place(){ 
     Gen *aux=Gens.back(); 
     aux->place(); 
     //Gens.push_back(new Gen(canvas)); 
    } 
    void moving(int x,int y){ 
     xPointer=x;yPointer=y; 
     if(Gens.size()==0){ 
      Gens.push_back(new Gen(canvas)); 
     } 
     else if (Gens.back()->placed==1){ 
      Gens.push_back(new Gen(canvas)); 
     } 
     Gen *aux=Gens.back(); 
     aux->updatePosition(x,y); 
     this->draw(); 
     cout<<"Elementos -> "<<Gens.size()<<"\n"; 
    } 
}; 





static gboolean 
moving(GtkWidget *da, GdkEvent *event, gpointer data) 
{ 

    int x, y; 
    GdkModifierType state; 
    gdk_window_get_device_position (gdk_event_get_window ((GdkEvent *) event), 
            gdk_event_get_device ((GdkEvent *) event), 
            &x, &y, &state); 
    /* 
    (void)event; (void)data; 
    ((Gen *)da)->draw();*/ 
    Map *g=(Map *)data; 
    g->moving(x,y); 
} 
static gboolean 
placing (GtkWidget *da, GdkEvent *event, gpointer data) 
{ 

    Map *g=(Map *)data; 
    g->place(); 

} 

int main (int argc, char **argv) { 


    GtkWidget *window; 
    GtkWidget *canvas; 
    gtk_init (&argc , &argv); 
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    gtk_widget_set_size_request (window, 
     500, 500); 

    g_signal_connect (window, "destroy", 
     G_CALLBACK (gtk_main_quit) , NULL); 
    canvas = gtk_drawing_area_new(); 
    Map *g=new Map(window,canvas); 
    gtk_container_add (GTK_CONTAINER (window), canvas); 
    gtk_widget_set_events(window, GDK_POINTER_MOTION_MASK); 

    //g_signal_connect (canvas, "draw", G_CALLBACK (drawing), (gpointer *)g); 
    g_signal_connect (window, "motion-notify-event", G_CALLBACK (moving), (gpointer *)g); 
    g_signal_connect (window, "button-press-event", G_CALLBACK (placing), (gpointer *)g); 

    //g_signal_connect (canvas, "motion-notify-event", (GCallback) on_window_draw, NULL); 

    gtk_widget_set_app_paintable(canvas, TRUE); 
    gtk_widget_show_all (window); 
    gtk_main(); 
    return 0; 
} 
+0

コードと混同しています。 gtkアプリケーションにCまたはC++を使用する予定ですか? – JohnKoch

+0

C++、申し訳ありませんが、私はそれを言っていませんでした:C –

答えて

3

いくつかの発言: ゲン:: PIXはGenオブジェクトが作成されるたびに割り当てられています。それは同じpixbufですが、スケーリング関数を使用する場合(つまり元のpixbufのメモリがリークしている場合)、別のものを作成します。これはそれぞれGenオブジェクトです。これは実際には不十分なので、静的なpixメンバを使用して、pixbufをロードしてメモリリークを修正すると、これを1回だけ行うことができます。

次に、ドローハンドラでgdk_cairo_createを呼び出していますが、GTK 3以降では、drawシグナルコールバックの入力パラメータとしてカイロコンテキストを取得することになっています。モーションイベントを通じてカスタムdrawメソッドを呼び出しているのが分かります。それはGTK +の描画スタックの仕組みではありません!右のそれを行うには

  • をメインには、ちょうどGenオブジェクトの位置を変更し、描画領域のためgtk_widget_queue_drawを呼び出して、あなたの運動のコールバックでGtkDrawingArea
  • draw信号に接続します。これにより、drawシグナルが鳴ります。
  • コールバックでdrawシグナルに接続した場合、与えられたカイロコンテキスト内のオブジェクトGenを再描画します。
  • パフォーマンスを向上させるには、カイロクリッピング関数を使用するか、gtk_widget_queue_drawの代わりにgtk_widget_queue_draw_areaまたはgtk_widget_queue_draw_regionを呼び出します。 drawコールバックで受け取るカイロコンテキストでは、あらかじめ計算されたクリッピング領域が得られます。これらのヒントを使用して、イメージのどの部分を再描画する必要があるかを正確に判断し、不必要な作業を回避できます。

公式ドキュメントでThe GTK+ Drawing Modelをお読みください。

+1

ありがとう!私は本当にあなたの答えをapreciatte!それは本当に多くの助けになりました! –

関連する問題