2

我想在树视图中放置一个复选框。当我单击复选框时,它应该检查。但是 Checkbox 一直没有被选中。我用 C 和 GTK3 编写了一个示例代码:

#include <gtk/gtk.h>

GtkTreeModel* create_model ()
{
    GtkTreeIter gti;
    GtkListStore *gls = gtk_list_store_new ( 1, G_TYPE_BOOLEAN );   
    gtk_list_store_append ( gls, &gti );
    gtk_list_store_set ( gls, &gti, 0, FALSE, -1 );
    return GTK_TREE_MODEL ( gls );
}

void check ( GtkCellRendererToggle *cell )
{
    int active = gtk_cell_renderer_toggle_get_active ( cell );
    g_print ( "%d\n", active );
    if ( active )
    {
        //fail
        gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE ( cell ), FALSE );
    }
    else
    {
        //fail
        gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE ( cell ), TRUE) ;
    }
    return;
}

int main ( int argc, char *argv[] )
{
    gtk_init ( &argc, &argv );
//window
    GtkWidget *window_main = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
//tree view
    GtkWidget *treeview = gtk_tree_view_new_with_model ( create_model ()    );
//cell_renderer_toggle
    GtkCellRenderer *cell = gtk_cell_renderer_toggle_new ();

    gtk_tree_view_append_column ( GTK_TREE_VIEW ( treeview ), gtk_tree_view_column_new_with_attributes ( "test", cell, "active",  0, NULL ) );
    g_signal_connect ( cell, "toggled", G_CALLBACK ( check ), NULL );

    gtk_container_add ( GTK_CONTAINER ( window_main ), treeview );  
    gtk_widget_show_all ( window_main );
    gtk_main();
    return 0;
}

函数 gtk_cell_renderer_toggle_set_active 调用失败并且没有设置单元格激活。请帮我修复我的代码。

4

1 回答 1

1

随着召唤

    gtk_tree_view_column_new_with_attributes ("test", cell, "active", 0, NULL);

您将"active"列中任何行中每个单元格渲染器的属性绑定到相关数据模型的第一列中的值。尽管任何GtkCellRendererToggle实例的状态都由其自身的属性表示,但它的"active"属性同时反映了数据模型中的相应值。

gtk_cell_renderer_toggle_set_active如果您通过设置"active"特定GtkCellRendererToggle实例的属性来激活单个单元格渲染器。不幸的是,该实例不知道它代表值的数据模型,因此无法访问它。这意味着在树视图的下一次绘制中,该"active"属性再次与数据模型中的相关值相对应。您的更改被简单地覆盖。

尽管如此,您仍然可以安全地设置未连接到数据模型的单元格渲染器的所有其他属性。我在我的示例中包含了一个示例。

这意味着您的回调必须更改数据模型中的值,而不是更改单元格渲染器的属性。

您的示例代码的附加修改说明了我所描述的


#include <gtk/gtk.h>

GtkListStore *
create_model ()
{
    GtkTreeIter gti;
    GtkListStore *gls;

    gls = gtk_list_store_new (1, G_TYPE_BOOLEAN);
    gtk_list_store_append (gls, &gti);
    gtk_list_store_set (gls, &gti, 0, TRUE, -1);

    return gls;
}

void
check (GtkCellRendererToggle * cell, gchar * path, GtkListStore * model)
{
    GtkTreeIter iter;
    gboolean active;

    active = gtk_cell_renderer_toggle_get_active (cell);

    gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &iter, path);

    if (active) {
        gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(cell), 0, 0);
        gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, FALSE, -1);
    }
    else {
        gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(cell), 0.5, 0.5);
        gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, TRUE, -1);
    }
}

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

    GtkTreeViewColumn *column;
    GtkWidget *window_main;
    GtkWidget *treeview;
    GtkCellRenderer *cell;
    GtkListStore *store;


    gtk_init (&argc, &argv);

    store = create_model ();

    //window
    window_main = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    //tree view
    treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));

    //cell_renderer_toggle
    cell = gtk_cell_renderer_toggle_new ();

    column =
        gtk_tree_view_column_new_with_attributes ("test",
                                                  cell, "active", 0, NULL);

    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

    g_signal_connect (cell, "toggled", G_CALLBACK (check), store);
    g_signal_connect (window_main, "destroy",
                      G_CALLBACK (gtk_main_quit), NULL);

    gtk_container_add (GTK_CONTAINER (window_main), treeview);
    gtk_widget_show_all (window_main);
    gtk_main ();

    return 0;
}
于 2013-08-12T09:17:42.733 回答