首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用rust-gnome时,如何将自己的数据放到GTK回调中?

在使用rust-gnome时,如何将自己的数据放到GTK回调中?
EN

Stack Overflow用户
提问于 2015-07-24 02:14:08
回答 1查看 736关注 0票数 3

..。或者,如何实现gtk::Widget的子类化?

我的Cargo.toml中有以下依赖项

代码语言:javascript
复制
[dependencies]
num = "*"
gtk = "*"
cairo-rs = "*"
gdk = "*"
time = "*"

我想创建我自己类型的小部件(用于渲染分形)。我有:

代码语言:javascript
复制
extern crate cairo;
extern crate gtk;

use cairo::Context;
use gtk::signal::Inhibit;
use gtk::signal::WidgetSignals;
use gtk::traits::ContainerTrait;
use gtk::traits::WidgetTrait;

struct MyWidget {
    widget: gtk::DrawingArea,
    foo: u32,
}

impl MyWidget {
    fn new() -> MyWidget {
        let result = MyWidget {
            widget: gtk::DrawingArea::new().unwrap(),
            foo: 17
        };
        result.widget.connect_draw(move |_w, c| {
            // Cannot do: result.redraw(c)
            Inhibit(true)
        });
        result
    }
    fn modify(&mut self, x: u32) {
        self.foo += x;
        self.widget.queue_draw();
    }
    fn redraw(&self, _ : Context) -> Inhibit {
        println!("Should redraw for {}", self.foo);
        Inhibit(true)
    }
}

fn main() {
    gtk::init().ok();
    let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();

    let area = MyWidget::new();
    window.add(&area.widget);
    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(true)
    });
    window.connect_key_release_event(move |_w, _event| {
        // Cannot do: area.modify(3);
        Inhibit(true)
    });
    window.connect_button_release_event(move |_w, _event| {
        // Cannot do: area.modify(17);
        Inhibit(true)
    });

    window.show_all();
    gtk::main();
}

但是当redraw被调用时,w当然是gtk::DrawingArea,而不是我的FractalWidget。我尝试过使用闭包来调用connect_draw,但是没有在其中使用result (我已经尝试过Boxing结果并将其moveing到lambda中,但我对此还不熟悉,所以可能有一些方法我还没有尝试过)。

所以,我的实际问题是:有没有办法将更多的数据发送到rust-gnome重绘方法(和其他类似的回调)中,或者有办法扩展小部件结构以包含我自己的数据?

EN

回答 1

Stack Overflow用户

发布于 2015-07-27 01:31:53

好的,这是一些实际工作的代码,主要是通过使用普通MyWidgetArc<Mutex<MyWidget>> insead。这仍然感觉相当笨拙,因为在进入闭包并锁定其中的互斥锁之前,我需要一个显式的克隆,但这可能是很好的做法(即使只有一个线程用于gtk事件)。也许冗长可以通过宏来修复...

代码语言:javascript
复制
extern crate cairo;
extern crate gtk;

use cairo::Context;
use gtk::signal::Inhibit;
use gtk::signal::WidgetSignals;
use gtk::traits::ContainerTrait;
use gtk::traits::WidgetTrait;
use std::sync::{Arc,Mutex};

struct MyWidget {
    widget: gtk::DrawingArea,
    foo: u32,
}

impl MyWidget {
    fn new() -> Arc<Mutex<MyWidget>> {
        let result = Arc::new(Mutex::new(MyWidget {
            widget: gtk::DrawingArea::new().unwrap(),
            foo: 17
        }));
        let r2 = result.clone();
        result.lock().unwrap().widget.connect_draw(move |_w, c| {
            r2.lock().unwrap().redraw(c)
        });
        result
    }
    fn modify(&mut self, x: u32) {
        self.foo += x;
        self.widget.queue_draw();
    }
    fn redraw(&self, _ : Context) -> Inhibit {
        println!("Should redraw for {}", self.foo);
        Inhibit(true)
    }
}

fn main() {
    gtk::init().ok();
    let window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();

    let area = MyWidget::new();
    window.add(&area.lock().unwrap().widget);
    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(true)
    });
    let a1 = area.clone();
    window.connect_key_release_event(move |_w, _event| {
        a1.lock().unwrap().modify(3);
        Inhibit(true)
    });
    let a2 = area.clone();
    window.connect_button_release_event(move |_w, _event| {
        a2.lock().unwrap().modify(17);
        Inhibit(true)
    });

    window.show_all();
    gtk::main();
}

我至少会等几天,并将这个答案标记为正确,以防有人有更好的答案。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31595115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档