在 rust 和 gtk4 中,为什么 gtk::Label 不满足 gtk::Widget?

In rust and gtk4, why does not gtk::Label satisfy gtk::Widget?

我正在尝试通过 gtk4 绑定来学习 Rust,并决定尝试 ListStore 作为 ListBox 的模型。为了绑定模型,需要 returns Widget 的函数,但我需要 Label。为什么继承 Widget(实现 IsA<Widget>)的 Label 不满足 Widget 类型?

错误:

error[E0308]: mismatched types
  --> src/main.rs:22:5
   |
21 | fn create_widget<'r>(label: &'r Object) -> Widget {
   |                                            ------ expected `gtk4::Widget` because of return type
22 |     Label::new(Some(label.property_value("name").get().unwrap()))
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `gtk4::Widget`, found struct `gtk4::Label`

完整代码:

use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Paned, Label, Orientation, ListBox, ListBoxRow, Widget};
use gtk::gio::ListStore;
use gtk::glib::Type;
use gtk::glib::Object;


fn main() {
    println!("Hello, world!");// Create a new application
    let app = Application::builder()
        .application_id("org.gtk-rs.example")
        .build();

    // Connect to "activate" signal of `app`
    app.connect_activate(build_ui);

    // Run the application
    app.run();
}

fn create_widget<'r>(label: &'r Object) -> Widget {
    Label::new(Some(label.property_value("name").get().unwrap()))
}

fn build_ui(app: &Application) {
    let listbox_left = ListBox::new();
    let listbox_right = ListBox::new();

    let list_model = ListStore::new(Type::STRING);

    listbox_right.bind_model(Some(&list_model), create_widget);


    let paned = Paned::builder()
        .start_child(&listbox_left)
        .end_child(&listbox_right)
        .orientation(Orientation::Horizontal)
        .build();


    // Create a window
    let window = ApplicationWindow::builder()
        .application(app)
        .title("My GTK App")
        .child(&paned)
        .build();

    for n in 1..11 {
        let n_as_string =(n as u32).to_string();
        let mut my = String::from("Left:");
        my.push_str(&n_as_string);

        let m = Object::with_values(Type::STRING, &[("name", my.to_value())]);

        list_model.append(&m.unwrap());
    }

    // Present window
    window.present();
}

继承不是 Rust 的语言特性。相反,gtk4 板条箱有 Label impl IsA<Widget> (here) which allows you to call Cast::upcast 这样的:

Label::new(Some(label.property_value("name").get().unwrap())).upcast()

您可能需要添加

use gtk4::glib::object::Cast;

到文件的顶部。 相反,你也可以让你的方法 return impl IsA<Widget> 代替。