![](/img/trans.png)
[英]Failed assertion '!_debugDoingThisLayout': is not true with StreamBuilder / ListView
[英]gtk4/rust failed assertion when removing EditableLabel from ListView
在下面的 gtk4 代码中,我试图通过删除相应的StringObject
从显示中删除EditableLabel
。 这应该在connect_editing_notify
回调指定的编辑完成后发生。
如果我使用返回键运行程序并退出编辑模式,那么它会按预期工作:标签消失。 但是,如果我通过选择不同的标签退出编辑模式,那么我会得到一个重复的控制台打印,说明断言失败:
(viewdb:13773): Gtk-CRITICAL **: 17:35:26.754: gtk_widget_get_parent: assertion 'GTK_IS_WIDGET (widget)' failed
(viewdb:13773): Gtk-CRITICAL **: 17:35:26.754: gtk_widget_get_parent: assertion 'GTK_IS_WIDGET (widget)' failed
(viewdb:13773): Gtk-CRITICAL **: 17:35:26.754: gtk_widget_get_parent: assertion 'GTK_IS_WIDGET (widget)' failed
编辑后如何干净地删除 EditableLabel ?
use gtk::glib::clone;
use gtk::prelude::*;
use gtk::{
Application, ApplicationWindow, EditableLabel, ListView, SignalListItemFactory,
SingleSelection, StringList, StringObject, Widget,
};
fn build_ui(app: &Application) {
let model: StringList = vec!["One", "Two", "Three", "Four"].into_iter().collect();
let selection_model = SingleSelection::new(Some(&model));
let factory = SignalListItemFactory::new();
factory.connect_setup(move |_, listitem| {
let label = EditableLabel::builder().build();
listitem.set_child(Some(&label));
listitem
.property_expression("item")
.chain_property::<StringObject>("string")
.bind(&label, "text", Widget::NONE);
label.connect_editing_notify(
clone!( @strong model, @strong listitem => move |lbl: &EditableLabel| {
if !lbl.is_editing() {
let position = listitem.position();
model.remove(position); // remove model entry cooresponding to edit.
}
}),
);
});
let view = ListView::new(Some(&selection_model), Some(&factory));
let window = ApplicationWindow::builder()
.application(app)
.child(&view)
.build();
window.present();
}
fn main() {
let app = Application::builder().build();
app.connect_activate(build_ui);
app.run();
}
在项目仍在处理某些事件时从其父项目中移除项目有时会导致问题。
简单的解决方法是在延迟函数中进行删除。 在 C 语言中,可以使用g_idle_add()
来完成,但正确使用会很麻烦。 但在 Rust 中,这非常简单:
gtk::glib::source::idle_add_local_once(
clone!(@strong model =>
move || model.remove(position)
)
);
但请注意,由于idle
函数会在未来某个未指定的时间运行,因此当回调运行时position
的值(列表中的普通索引)可能会引用不同的项目,尽管可能性很小。
我没有测试它,但我认为将listitem
本身保留在回调中更明智:
gtk::glib::source::idle_add_local_once(
clone!(@strong model, @weak listitem =>
move || {
let position = listitem.position();
if position != INVALID_LIST_POSITION {
model.remove(position)
}
}
)
);
弱克隆将确保仅在项目仍然存在时才调用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.