微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我们如何使用 rust 中的glade、gtk-rs 构建GUI?

如何解决我们如何使用 rust 中的glade、gtk-rs 构建GUI?

我使用glade创建了一个带有窗口、输入框、标签和按钮的简单GUI,并在我的rust项目的example.glade目录中保存为src

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow">
    <property name="can_focus">False</property>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkFixed" id="windows1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="gtkbutton" id="button1">
            <property name="label" translatable="yes">button</property>
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="x">182</property>
            <property name="y">146</property>
          </packing>
        </child>
        <child>
          <object class="GtkEntry" id="Box1">
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
          </object>
          <packing>
            <property name="x">68</property>
            <property name="y">45</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">label</property>
          </object>
          <packing>
            <property name="x">321</property>
            <property name="y">44</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

我的目标是创建一个简单的 Rust 应用程序,当在输入框中输入值并通过单击按钮提交时,它会更改标签名称

我尝试使用 this example 和 gtk-rs v0.9.2 编写 Rust 后端。这是我的代码

use gtk::glib;
use gtk::prelude::*;
use gtk::{applicationwindow,Builder,Button,MessageDialog};

use std::env::args;

fn build_ui(application: &gtk::Application) {
    let glade_src = include_str!("example.glade");
    let builder = Builder::from_string(glade_src);
    let window: applicationwindow = builder.get_object("window1").expect("Couldn't get window1");

    window.show_all();
}


fn main() {
    let application = gtk::Application::new(
        Some("com.github.gtk-rs.examples.builder_basics"),Default::default(),)
    .expect("Initialization Failed...");

    application.connect_activate(build_ui);

    application.run(&args().collect::<Vec<_>>());
}

运行时出现以下错误

error: extern crate `glib` is private,and cannot be re-exported (error E0365),consider declaring with `pub`
 --> src/main.rs:1:5
  |
1 | use gtk::glib;


error[E0599]: no method named `connect_activate` found for struct `Application` in the current scope
  --> src/main.rs:23:17
   |
23 |       application.connect_activate(build_ui);
   |                   ^^^^^^^^^^^^^^^^ method not found in `Application`


error[E0599]: no method named `run` found for struct `Application` in the current scope
  --> src/main.rs:25:17
   |
25 |       application.run(&args().collect::<Vec<_>>());
   |                   ^^^ method not found in `Application`

我们如何用glade、gtk-rs in rust构建GUI?

#Cargo.toml
[dependencies]
gtk = "0.9.2"

解决方法

我不能说这是做到这一点的聪明/正确的方法,但请注意您的错误。

glib 是它自己的依赖项,因此在您的 cargo.toml 中添加它。 我认为您需要的最低限度是:

[dependancies]
gio = {version = "*",features =["v2_44"]}
glib = "*"
gtk = {version = "*",features =["v3_16"]}
gdk = "*"

我的程序特别需要的一些功能。

我的 use 语句如下:

// imports for GTK UI windows
use gio::prelude::*;
use gtk::prelude::*;
use glib;

use gtk::{Button} // as an example widget

前奏应该有助于解决连接和运行等缺失的功能。

我跑步的主要内容是这个,与你的相似但不一样:

// gtk UI setup an run
    let application =
        gtk::Application::new(Some("Program name"),Default::default())
            .expect("Initialization failed...");
    
    application.connect_activate(|app| {
        build_ui(app);
    });
    
    application.run(&args().collect::<Vec<_>>());
,

由于缺乏好的文档、教程或帮助,它真的很难在 Rust 中编程。我不得不梳理许多站点并复制过去编辑许多示例代码才能使这件事正常工作。首先我们必须在cargo.toml文件中指定一个版本,版本必须是我们安装的gtk3,gio版本。现在我的依赖项看起来像这样。

[dependencies]
glib = "0.10.3"

[dependencies.gtk]
version = "0.9.2"
features = ["v3_XX"] // XX our gtk3 sub version

[dependencies.gio]
version = "0.9.1"
features = ["v2_XX"] // XX our gio sub version

然后我编辑了我的空地文件以使用处理程序 _on_clicked

设置信号事件
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkButton" id="button1">
            <property name="label" translatable="yes">button</property>
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <signal name="clicked" handler="_on_clicked" swapped="no"/>
          </object>
          <packing>
            <property name="x">182</property>
            <property name="y">146</property>
          </packing>
        </child>
        <child>
          <object class="GtkEntry" id="box1">
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
          </object>
          <packing>
            <property name="x">68</property>
            <property name="y">45</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label1">
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">label</property>
          </object>
          <packing>
            <property name="x">321</property>
            <property name="y">44</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

这是我在rust中对应的逻辑

extern crate gtk;
extern crate gio;    

use gtk::prelude::*;
use gio::prelude::*;

use gtk::{Builder,Window,Button};

use std::env::args;

// the handler
fn on_clicked(param: &[glib::Value]) -> Option<glib::Value> {
    println!("on_start_clicked fired!");
    None
}

fn build_ui(application: &gtk::Application) {
    let glade_src = include_str!("example.glade");
    let builder = Builder::from_string(glade_src);

    let window: Window = builder.get_object("window1").expect("Couldn't get window");
    
    window.set_application(Some(application));
    window.set_title("Test");
    
    window.connect_delete_event(|_,_| {
            gtk::main_quit();
            Inhibit(true)
        });

     // directly calling the button1 without implementing signal
    //let btn: Button = builder.get_object("button1").expect("Cant get button");
    //btn.connect_clicked(|_| {
            //println!("Activated");
        //});


    builder.connect_signals(|builder,handler_name| {
    match handler_name {
        // handler_name as defined in the glade file => handler function as defined above
        "_on_clicked" => Box::new(on_clicked),_ => Box::new(|_| {None})
    }
});
    
    window.show_all();
}

fn main() {
    let application = gtk::Application::new(
        Some("com.test.app"),Default::default(),)
    .expect("Initialization failed...");

    application.connect_activate(|app| {
        build_ui(app);
    });

    application.run(&args().collect::<Vec<_>>());
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。