【问题标题】:Redrawing a widget in Gtk在 Gtk 中重绘一个小部件
【发布时间】:2010-06-25 13:05:20
【问题描述】:

我正在尝试使用 gtk_widget_queue_draw 函数重绘 GtkDrawingArea,但小部件没有重绘。

代码如下,gtk_widget_queue_draw 在按钮按下事件回调函数中。

static gboolean click(GtkWidget *board,GdkEventButton *event,gpointer parentWindow){
    static int origen = -1;
    static int destino = -1;

    if(origen == -1){
        mapeo(&origen, event->x, event->y);
    }else{
       mapeo(&destino, event->x, event->y);
    if(!movimiento_fichas(JUGADOR_DOS, origen - 1, destino - 1)){
        dialogoMovInvalido(parentWindow); //displays a warning dialog
        g_print("%d %d", origen, destino); //debugging console output
        origen = -1; destino = -1;
    }else{
        g_print("%d %d", origen, destino); //debugging console output
        gtk_widget_queue_draw(board); //Here's where the redrawing is supossed to occur.
       }
    }

    return 0;
}

公开事件回调

static gboolean onExposeEvent(GtkWidget *widget,GdkEventExpose *event,gpointer data){
    cairo_t *cr;
    cairo_surface_t *fondo;
    cairo_surface_t *ficha_roja;
    cairo_surface_t *ficha_blanca;

gint i,j;

cr = gdk_cairo_create(widget->window);

fondo = cairo_image_surface_create_from_png("interfaz.png");
ficha_roja = cairo_image_surface_create_from_png("ficha_roja.png");
ficha_blanca = cairo_image_surface_create_from_png("ficha_blanca.png");

cairo_set_source_surface(cr, fondo, 0, 0);
cairo_paint(cr);

for(i=0; i<24; i++){
    if(tablero[i].player == JUGADOR_UNO){
        cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y);
        for(j=1; j<=tablero[i].num; j++){
            cairo_paint(cr);
            cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y);
            if(i < 12)
                cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y - (j*25));
            else
                cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y + (j*25));
        }
    }else if(tablero[i].player == JUGADOR_DOS){
        cairo_set_source_surface(cr, ficha_roja, posiciones[i].x, posiciones[i].y);
        for(j=1; j<=tablero[i].num; j++){
            cairo_paint(cr);
            if(i < 12)
                cairo_set_source_surface(cr, ficha_roja, posiciones[i].x, posiciones[i].y - (j*25));
            else
                cairo_set_source_surface(cr, ficha_roja, posiciones[i].x, posiciones[i].y + (j*25));
        }
    }
}

cairo_destroy(cr);

return 0;
}

Expose-event 和 button-press-event 连接(都在创建顶级窗口的函数内)。

  g_signal_connect(G_OBJECT(board),"expose-event",G_CALLBACK(onExposeEvent),NULL);
  g_signal_connect(G_OBJECT(board),"button-press-event",G_CALLBACK(click),window);

主要功能。

int main(int argc, char *argv[]){
    gtk_init(&argc, &argv);

    mainWindow(); //Creates the main window

    gtk_main();

    return 0;
}

【问题讨论】:

    标签: c gtk


    【解决方案1】:

    由于您没有粘贴所有相关代码,因此无法确定性地指出问题所在。无论如何,我认为可能有两个错误/误解会导致您的问题。

    • 您应该只在expose-event 信号处理程序中绘制。虽然可以在外部绘图,但此类绘图不会更新,并且可能由于多种原因而完全丢失,包括此类自行启动的重绘。
    • 重绘将异步进行。 IE。在不同的主循环运行。如果您以非标准方式运行主循环,这可能会出现问题,例如使用gtk_events_pending()/gtk_main_iteration()

    最后,检查board 确实是您要重绘的小部件。可能是你在连接click()时传递了错误的用户数据。

    【讨论】:

    • 绘图是在一个暴露事件回调函数中完成的,它在初始绘图发生后就开始工作了。问题是我需要在鼠标点击后重新绘制 GtkDrawingArea(我过去做过,有一段时间没碰过 gtk 所以我有点生疏了)
    • @dailen:安排重绘后是否调用onExposeEvent?你如何运行主循环?
    • 主循环相当简单。我的程序是这样的,在 mainWindow() 中是关于窗口属性、信号连接以及所有其他小部件(顶层窗口的儿子)的所有代码。我只想在点击几下后能够更新 GtkDrawingArea,因为 afaik gtk_widget_queue_draw 应该调用“expose-event”回调来重绘小部件。
    • @dallen:它不应该调用,而是安排重绘,在单独的主循环迭代中运行。是完全调用回调(意味着发出信号)还是不调用?你使用自定义的主循环迭代代码吗?
    • 第一次创建窗口时,onExposeEvent() 函数会完成它应该进行的所有绘图。调用 gtk_widget_queue_draw() 后不会。
    【解决方案2】:

    找到答案了,gtk代码没有问题。特定于我的程序的代码导致了错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多