rust 如何限制GtkColumnView行数

xuo3flqw  于 2023-08-05  发布在  其他
关注(0)|答案(3)|浏览(129)

我正在尝试减少具有大量行的ColumnView小部件的加载时间。引用自gtk list widget documentation
虽然短列表为模型中的每个项目示例化小部件不是问题,但一旦列表增长到数千或数百万个元素,这就变得不太可行了。因此,视图只创建有限数量的列表项,并通过将它们绑定到新项来回收它们。一般来说,视图试图保持列表项可用仅用于实际上可以在屏幕上看到的项目
然而在我的代码示例中,虽然回收(绑定,解除绑定)工作;设置了205个项目;而只有少数项目是可见的:

use gtk::*;
use gtk::prelude::*;
use gtk::gio::ListStore;
use gtk::glib::BoxedAnyObject;

fn main() {
    let application = Application::builder().application_id("column.view.test").build();
    application.connect_activate(|application| {
        let list_store = ListStore::new(BoxedAnyObject::static_type());
        for i in 0..10000 {
            list_store.append(&BoxedAnyObject::new(i));
        }
        let column_view = ColumnView::builder().model(&NoSelection::new(Some(list_store))).build();
        let scrolled_window = ScrolledWindow::builder().child(&column_view).build();
        let item_factory = SignalListItemFactory::new();
        item_factory.connect_setup(|_, item| {
            let list_item = item.downcast_ref::<ListItem>().unwrap();
            list_item.set_child(Some(&Label::new(None)));
            println!("setup");
        });
        item_factory.connect_bind(|_, item| {
            let list_item = item.downcast_ref::<ListItem>().unwrap();
            list_item.child().and_downcast::<Label>().unwrap().set_label("a");
            println!("bind");
        });
        item_factory.connect_unbind(|_, _| { println!("unbind"); });
        item_factory.connect_teardown(|_, _| { println!("teardown"); });
        column_view.append_column(&ColumnViewColumn::builder().factory(&item_factory).build());
        ApplicationWindow::builder().application(application).child(&scrolled_window).build().present();
    });
    application.run();
}

字符串
我如何才能只设置可见的项目(或更多)或硬编码的项目数量,以减少我的小部件的加载时间?

yqyhoc1h

yqyhoc1h1#

简短的回答是:你不能。我在尝试使用一些重量级的大项目时也遇到了同样的问题(Texteditor,WEBKit视图)。小部件正在开发中,如果您确实认为需要,您可能需要创建自己的小部件。至少我是这么做的。

qxsslcnc

qxsslcnc2#

控制小部件设置的项目数量是不可能的,这是基于几个因素而不仅仅是可见项目的数量来决定的。您可以尝试的一件事是使用GtkSliceListModel拆分模型,控制提供给小部件的项的数量,并间接决定每次可以设置多少项。

luaexgnf

luaexgnf3#

我尝试了Kripto的建议,使用GtkSliceListModel,但仍然有很多的设置和拆除发生,所以没有太多的回收;但是,您可以通过这种方式减少初始项设置,从而减少小部件的加载时间。

const PAGE_SIZE: u32 = 40;
const TOTAL: i32 = 100;

fn main() {
    let application = Application::builder().application_id("column.view.test").build();
    application.connect_activate(|application| {
        let list_store = ListStore::new::<BoxedAnyObject>();
        let slice_list_model = SliceListModel::builder().model(&list_store).size(PAGE_SIZE).build();
        for i in 1..TOTAL {
            list_store.append(&BoxedAnyObject::new(i));
        }
        let column_view = ColumnView::builder().build();
        column_view.connect_realize({
            let slice_list_model = slice_list_model.clone();
            move |column_view| {
                column_view.vadjustment().unwrap().connect_value_changed({
                    let slice_list_model = slice_list_model.clone();
                    let last_value = Cell::new(0.0);
                    let value_change_because_of_offset_change = Cell::new(false);
                    move |adjustment| {
                        if value_change_because_of_offset_change.get() {
                            value_change_because_of_offset_change.set(false);
                        } else {
                            let value = adjustment.value();
                            let fraction = value / (adjustment.upper() - adjustment.page_size());
                            let delta = if fraction > 0.7 && last_value.get() < value {
                                10
                            } else if fraction < 0.3 && last_value.get() > value {
                                -10
                            } else { 0 };
                            last_value.set(value);
                            if delta != 0 {
                                value_change_because_of_offset_change.set(true);
                                slice_list_model.set_offset((slice_list_model.offset() as i32 + delta)
                                    .clamp(0, TOTAL - PAGE_SIZE as i32) as u32);
                            }
                        }
                    }
                });
            }
        });
        column_view.set_model(Some(&NoSelection::new(Some(slice_list_model))));
        let scrolled_window = ScrolledWindow::builder().child(&column_view).build();
        let item_factory = SignalListItemFactory::new();
        let setup_count = Cell::new(0);
        item_factory.connect_setup(move |_, item| {
            let list_item = item.downcast_ref::<ListItem>().unwrap();
            list_item.set_child(Some(&Label::new(None)));
            setup_count.set(setup_count.get() + 1);
            println!("setup {}", setup_count.get());
        });
        let bind_count = Cell::new(0);
        item_factory.connect_bind(move |_, item| {
            let list_item = item.downcast_ref::<ListItem>().unwrap();
            let string = list_item.item().and_downcast::<BoxedAnyObject>().unwrap().borrow::<i32>().to_string();
            list_item.child().and_downcast::<Label>().unwrap().set_label(&string);
            bind_count.set(bind_count.get() + 1);
            println!("bind {}", bind_count.get());
        });
        let unbind_count = Cell::new(0);
        item_factory.connect_unbind(move |_, _| {
            unbind_count.set(unbind_count.get() + 1);
            println!("unbind {}", unbind_count.get());
        });
        let teardown_count = Cell::new(0);
        item_factory.connect_teardown(move |_, _| {
            teardown_count.set(teardown_count.get() + 1);
            println!("teardown {}", teardown_count.get());
        });
        column_view.append_column(&ColumnViewColumn::builder().factory(&item_factory).build());
        ApplicationWindow::builder().application(application).child(&scrolled_window).build().present();
    });
    application.run();
}

字符串

相关问题