..。或者,如何实现gtk::Widget的子类化?
我的Cargo.toml中有以下依赖项
[dependencies]
num = "*"
gtk = "*"
cairo-rs = "*"
gdk = "*"
time = "*"我想创建我自己类型的小部件(用于渲染分形)。我有:
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重绘方法(和其他类似的回调)中,或者有办法扩展小部件结构以包含我自己的数据?
发布于 2015-07-27 01:31:53
好的,这是一些实际工作的代码,主要是通过使用普通MyWidget的Arc<Mutex<MyWidget>> insead。这仍然感觉相当笨拙,因为在进入闭包并锁定其中的互斥锁之前,我需要一个显式的克隆,但这可能是很好的做法(即使只有一个线程用于gtk事件)。也许冗长可以通过宏来修复...
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();
}我至少会等几天,并将这个答案标记为正确,以防有人有更好的答案。
https://stackoverflow.com/questions/31595115
复制相似问题