【问题标题】:How do we build GUI with glade, gtk-rs in rust?我们如何在 rust 中使用 glade、gtk-rs 构建 GUI?
【发布时间】:2023-03-17 06:51:01
【问题描述】:

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

<?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`

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

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

【问题讨论】:

    标签: rust gtk glade gtk-rs


    【解决方案1】:

    我不能说这是聪明/正确的方法,但要看看你的错误。

    glib 是它自己的依赖项,所以在你的 cargo.toml 中添加它。 我认为您需要的最低要求是:

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

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

    我的使用声明如下:

    // 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<_>>());
    

    【讨论】:

      【解决方案2】:

      由于缺乏好的文档、教程或帮助,在 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
      

      然后我编辑了我的 glade 文件以使用处理程序 _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<_>>());
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-31
        • 1970-01-01
        • 1970-01-01
        • 2012-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多