如何"check" GtkCellRendererToggle?
How to "check" GtkCellRendererToggle?
我想要一个简单的复选框 "check" 当我点击它时,但我发现这非常棘手,互联网上几乎没有示例!
GtkTreeView *tree_view;
GtkListStore *list_store;
GtkTreeModelFilter *filter_model;
static int populate_row_callback (void *data, int colCount, char *values[], char *colNames[]) {
GtkTreeIter row_iter;
gtk_list_store_append (list_store, &row_iter);
gtk_list_store_set (list_store, &row_iter, COL_DOWNLOAD, TRUE,
... // more cols
-1);
return 0;
}
void populate_grid () {
gtk_list_store_clear (list_store);
syn_get_data (populate_row_callback); // gets data from sqlite
}
static void activate (GtkApplication* app, gpointer user_data) {
GtkBuilder *builder = gtk_builder_new_from_file ("window.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
search_toggle = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "search_toggle"));
search_bar = GTK_SEARCH_BAR (gtk_builder_get_object (builder, "search_bar"));
search_entry = GTK_SEARCH_ENTRY (gtk_builder_get_object (builder, "search_entry"));
tree_view = GTK_TREE_VIEW (gtk_builder_get_object (builder, "tree_view"));
list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "list_store"));
filter_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (list_store), NULL));
gtk_builder_connect_signals (builder, NULL);
g_object_unref (builder);
gtk_widget_show_all (window);
populate_grid ();
gtk_tree_model_filter_set_visible_func (filter_model, search_filter_func, NULL, NULL);
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (filter_model));
gtk_main ();
}
void download_toggled (GtkCellRendererToggle *cell, gchar *path_string, gpointer user_data) {
GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
GtkTreeIter rowIter;
if (gtk_tree_model_get_iter (model, &rowIter, path)) {
gboolean checked = gtk_cell_renderer_toggle_get_active (cell);
// gtk_cell_renderer_toggle_set_active (cell, !checked); // effects every row!
gtk_list_store_set (list_store, &rowIter, 0, !checked, -1); // causes runtime critical warning
}
}
我还尝试在同一处理程序中使用 GtkListStore
:
gtk_list_store_set (list_store, &rowIter, 0, !checked, -1);
但这不起作用,我得到:
Gtk-CRITICAL **: gtk_list_store_set_valist: assertion 'iter_is_valid (iter, list_store)' failed
这是因为 Iter
rowIter 不是使用 row_store 获取的,但话又说回来,我无法使用它获取它,因为它没有 get 方法...
您的 GtkListStore 嵌入在 GtkTreeModelFilter 中,因此您创建的任何 GtkTreePaths 和 GtkTreeIters 都将特定于 GtkTreeModelFilter。为了能够修改底层 GtkTreeModel,您必须使用 gtk_tree_model_filter_convert_iter_to_child_iter()
函数将 GtkTreeModelFilter 的 GtkTreeIter 转换为底层 GtkListStore 的 GtkTreeIter。在原始代码的 download_toggled()
.
的 if 块内调用它
如果您将 GtkTreeModelSort 添加到等式中,同样适用。如果您同时使用两者,则必须以正确的顺序为两者调用等效的 iter_to_child_iter
函数——这就像一层一层地剥洋葱。
我想要一个简单的复选框 "check" 当我点击它时,但我发现这非常棘手,互联网上几乎没有示例!
GtkTreeView *tree_view;
GtkListStore *list_store;
GtkTreeModelFilter *filter_model;
static int populate_row_callback (void *data, int colCount, char *values[], char *colNames[]) {
GtkTreeIter row_iter;
gtk_list_store_append (list_store, &row_iter);
gtk_list_store_set (list_store, &row_iter, COL_DOWNLOAD, TRUE,
... // more cols
-1);
return 0;
}
void populate_grid () {
gtk_list_store_clear (list_store);
syn_get_data (populate_row_callback); // gets data from sqlite
}
static void activate (GtkApplication* app, gpointer user_data) {
GtkBuilder *builder = gtk_builder_new_from_file ("window.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
search_toggle = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "search_toggle"));
search_bar = GTK_SEARCH_BAR (gtk_builder_get_object (builder, "search_bar"));
search_entry = GTK_SEARCH_ENTRY (gtk_builder_get_object (builder, "search_entry"));
tree_view = GTK_TREE_VIEW (gtk_builder_get_object (builder, "tree_view"));
list_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "list_store"));
filter_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (list_store), NULL));
gtk_builder_connect_signals (builder, NULL);
g_object_unref (builder);
gtk_widget_show_all (window);
populate_grid ();
gtk_tree_model_filter_set_visible_func (filter_model, search_filter_func, NULL, NULL);
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (filter_model));
gtk_main ();
}
void download_toggled (GtkCellRendererToggle *cell, gchar *path_string, gpointer user_data) {
GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
GtkTreeIter rowIter;
if (gtk_tree_model_get_iter (model, &rowIter, path)) {
gboolean checked = gtk_cell_renderer_toggle_get_active (cell);
// gtk_cell_renderer_toggle_set_active (cell, !checked); // effects every row!
gtk_list_store_set (list_store, &rowIter, 0, !checked, -1); // causes runtime critical warning
}
}
我还尝试在同一处理程序中使用 GtkListStore
:
gtk_list_store_set (list_store, &rowIter, 0, !checked, -1);
但这不起作用,我得到:
Gtk-CRITICAL **: gtk_list_store_set_valist: assertion 'iter_is_valid (iter, list_store)' failed
这是因为 Iter
rowIter 不是使用 row_store 获取的,但话又说回来,我无法使用它获取它,因为它没有 get 方法...
您的 GtkListStore 嵌入在 GtkTreeModelFilter 中,因此您创建的任何 GtkTreePaths 和 GtkTreeIters 都将特定于 GtkTreeModelFilter。为了能够修改底层 GtkTreeModel,您必须使用 gtk_tree_model_filter_convert_iter_to_child_iter()
函数将 GtkTreeModelFilter 的 GtkTreeIter 转换为底层 GtkListStore 的 GtkTreeIter。在原始代码的 download_toggled()
.
如果您将 GtkTreeModelSort 添加到等式中,同样适用。如果您同时使用两者,则必须以正确的顺序为两者调用等效的 iter_to_child_iter
函数——这就像一层一层地剥洋葱。