2017-09-29 2 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를로드 한 다음 메모리 누수를 수정하면이 작업을 한 번만 수행 할 수 있습니다.

그러면 draw 핸들러에서 gdk_cairo_create을 호출하지만 GTK 3 이후에는 draw 신호 콜백에서 입력 매개 변수로 카이로 컨텍스트를 가져와야합니다. 모션 이벤트를 통해 사용자 정의 draw 메서드를 호출하는 것을 볼 수 있습니다. GTK + 드로잉 스택이 작동하는 방식이 아닙니다! 단지 Gen 객체의 위치를 ​​변경합니다 GtkDrawingArea 모션 콜백에서

  • draw 신호에 연결 주에

    • 를 도면 영역에 대한 gtk_widget_queue_draw 전화 :

      바로 그것을 할 . 그러면 draw 신호가 발동됩니다.
    • 신호가 draw 신호에 연결되어 있으면 주어진 카이로 컨텍스트에서 Gen 개체를 다시 그립니다.
    • 성능 향상을 위해 카이로 클리핑 함수를 사용하거나 gtk_widget_queue_draw 대신 gtk_widget_queue_draw_area 또는 gtk_widget_queue_draw_region으로 호출 할 수 있습니다. draw 콜백에서받을 카이로 컨텍스트에서 미리 계산 된 클리핑 영역을 얻을 수 있습니다. 이러한 힌트를 사용하여 이미지의 어떤 부분을 다시 그려야 하는지를 정확하게 결정할 수 있으며 불필요한 작업을 피할 수 있습니다.

    공식 문서에서 The GTK+ Drawing Model을 읽으십시오.

  • +1

    고마워요! 나는 정말로 당신의 답을 모독합니다! 정말 많은 도움이되었습니다! –

    관련 문제