GTK函数GTK_tree_view_scroll_to_cell()的不可靠行为



我需要一些帮助来理解为什么使用GtkTreeView的某些代码中会出现错误,以及如何修复它。

在程序中,用户打开一个图像并运行一个功能来检测图像中的恒星。这一切都是可靠的,运行良好。每个恒星的数据都被填充到GtkTreeView中。

然后,用户点击显示屏上的一个星号,该星号会触发回调:

gboolean on_drawingarea_button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)

然后调用下面显示的函数:

void set_iter_of_clicked_psf(double x, double y) {
GtkTreeSelection *selection = GTK_TREE_SELECTION(gtk_builder_get_object(gui.builder, "treeview-selection"));
GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget("Stars_stored"));
GtkTreeModel *model = gtk_tree_view_get_model(treeview);
GtkTreeIter iter;
gboolean valid;
gboolean is_as;
const double radian_conversion = ((3600.0 * 180.0) / M_PI) / 1.0E3;
double invpixscalex = 1.0;
double bin_X = gfit.unbinned ? (double) gfit.binning_x : 1.0;
if (com.stars && com.stars[0]) {// If the first star has units of arcsec, all should have
is_as = (strcmp(com.stars[0]->units,"px"));
} else {
return; // If com.stars is empty there is no point carrying on
}
if (is_as) {
invpixscalex = 1.0 / (radian_conversion * (double) gfit.pixel_size_x / gfit.focal_length) * bin_X;
}
valid = gtk_tree_model_get_iter_first(model, &iter);
while (valid) {
gdouble xpos, ypos, fwhmx;
gtk_tree_model_get(model, &iter, COLUMN_X0, &xpos, -1);
gtk_tree_model_get(model, &iter, COLUMN_Y0, &ypos, -1);
gtk_tree_model_get(model, &iter, COLUMN_FWHMX, &fwhmx, -1);
fwhmx *= invpixscalex;
gdouble distsq = (xpos - x) * (xpos - x) + (ypos - y) * (ypos - y);
gdouble psflimsq = 6. * fwhmx * fwhmx;
if (distsq < psflimsq) {
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
if (!path) return;
gtk_tree_selection_select_path(selection, path);
gtk_tree_view_scroll_to_cell(treeview, path, NULL, TRUE, 0.5, 0.0);
gtk_tree_path_free(path);
gui.selected_star = get_index_of_selected_star(xpos, ypos);
display_status();
redraw(REDRAW_OVERLAY);
return;
}
valid = gtk_tree_model_iter_next(model, &iter);
}
siril_debug_print("Point clicked does not correspond to a known starn");
return;
}

代码遍历GtkTreeView中的每个iter,并检查单击的位置是否离恒星的中心足够近:然后代码的关键位跟随在条件内,直到函数结束。如果位置与恒星匹配,则会根据iter声明并初始化GtkTreePath,将选择更改为该路径,并调用gtk_tree_view_scroll_to_cell((,该函数用于滚动GtkTreeView,以便显示所选恒星。

对于一些用户来说,代码每次都会起作用,并导致树状视图滚动到选定的星形。对于其他用户来说,有时它有效,有时它不起作用。当它不起作用时,我可以告诉你遵循了正确的代码路径,因为gui.selected_star更新正确(它会在随后的重绘(redraw_OVERLAY(调用中触发绘图事件(。只有gtk_tree_view_scroll_to_cell((似乎运行不正常。

我和我的一位开发人员都不明白为什么它有时有效,但并不总是有效,也不明白为什么有些用户根本看不到这个bug。所以,如果任何GTK大师能启发我,我将不胜感激!

我有时也会遇到这个奇怪的错误。我注意到,如果在尝试预成型滚动之前打开和关闭了模态对话框,并且模态没有被破坏,也会出现这个错误。树视图滚动消息因此受到影响。这让我相信,一些函数或回调可能会干扰滚动,而那些干扰的函数或回调必须在调用滚动函数之前完成所有消息泵处理。

总之,我认为问题是Gtk事件循环(或者windows用户可能称之为消息循环(

我怀疑下面的一个变通解决方案可能会解决您的问题。他们解决了我过去的问题。

解决方案1(如果模式对话框在滚动事件之前打开,而在滚动之前未销毁。避免在调用gtk_tree_view_scroll_to_cell((之前打开模式对话框

解决方案2(如果必须在滚动事件之前使用模式对话框,请在调用gtk_tree_view_scroll_to_cell((之前销毁模式对话框。

解决方案3(为稍后调用的gtk_tree_view_scroll_to_cell((设置计时器。这允许消息泵完成处理滚动之前需要处理的挂起消息(可能是您当前所处功能的结果(。500ms计时器在我的一个程序中运行良好。

解决方案4(如果模式对话框还不能被销毁,或者您所在的函数导致了这个问题。确保任何模态都不再控制消息循环,并且除了main之外,没有其他内容控制消息循环。然后在调用gtk_tree_view_scroll_to_cell((之前处理挂起的消息,下面是处理挂起消息的代码。

/*process pending messages*/ while(gtk_events_pending()){gtk_main_iteration();}

最新更新