使用rust gnome时,如何将自己的数据发送到GTK回调?
。。。或者,如何为gtk::Widget子类化 我的使用rust gnome时,如何将自己的数据发送到GTK回调?,gtk,rust,rust-gnome,Gtk,Rust,Rust Gnome,。。。或者,如何为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::Widge
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::drawingara
而不是我的FractalWidget
。我一直在努力调用带有闭包的connect\u draw
,但没有在其中使用result
(我尝试了Box
,然后将结果移动到lambda中,但我是新手,所以可能有一些方法我没有尝试过)
所以,我的实际问题是:有没有一种方法可以将更多的数据发送到rust gnome重画方法(和其他类似的回调),或者有没有一种方法可以扩展一个小部件结构来包含我自己的数据?好的,下面是一些实际工作的代码,主要是通过使用Arc
插入普通MyWidget
。这仍然感觉相当笨拙,因为在进入闭包并锁定其中的互斥锁之前,我需要一个显式克隆,但这可能是一件好事(即使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();
}
extern板条箱开罗;
外部板条箱gtk;
使用cairo::Context;
使用gtk::信号::抑制;
使用gtk::signal::WidgetSignals;
使用gtk::traits::ContainerTrait;
使用gtk::traits::WidgetTrait;
使用std::sync::{Arc,Mutex};
结构MyWidget{
小部件:gtk::DrawingArea,
foo:u32,
}
impl-MyWidget{
fn new()->Arc{
让结果=弧::新(互斥体::新(MyWidget{
小部件:gtk::DrawingArea::new().unwrap(),
傅:17
}));
设r2=result.clone();
result.lock().unwrap().widget.connect|u draw(move|u w,c|{
r2.锁定().展开().重绘(c)
});
结果
}
fn修改(&mut self,x:u32){
self.foo+=x;
self.widget.queue_draw();
}
fn重画(&self,uquo:Context)->禁止{
println!(“应该为{}重新绘制,self.foo);
抑制(真)
}
}
fn main(){
gtk::init().ok();
让window=gtk::window::new(gtk::WindowType::TopLevel).unwrap();
let area=MyWidget::new();
添加(&area.lock().unwrap().widget);
window.connect_delete_事件(| |,|{
gtk::main_quit();
抑制(真)
});
设a1=area.clone();
窗口。连接按键释放事件(移动、事件){
a1.锁定().展开().修改(3);
抑制(真)
});
设a2=area.clone();
窗口。连接按钮释放事件(移动事件){
a2.锁定().展开().修改(17);
抑制(真)
});
window.show_all();
gtk::main();
}
如果有人有更好的答案,我会把这个答案标记为正确答案,至少等几天。好的,我试着让它更准确一点。。。现在redraw函数尝试使用FractalWidget的一个成员,就像它是w的一个成员一样,这显然不起作用。事实上,我已经找到了一种方法,所以我也会添加一个答案。哈哈,我发现,这通常是创建MCVE的好处之一。它迫使你从一个新的角度来看待问题,真正关注错误^_^请注意,更新后的代码仍然存在错误(未终止的字符串、缺少分号、缺少导入、未定义的变量区域
,…)。只有当我们能够将它粘贴到一个全新的文件中并使其工作时,它才真正有用。事实上,我在尝试使它MCVE:ish之前找到了我的半解决方案,但我原则上同意…:-)你知道如何在gtk rs的绘图区域内绘制像素吗?@Moebius:嗯,有点。因为我画了很多像素,所以我把它们放在一个Pixbuf中,然后使用set_source_Pixbuf(…)、rectangle(…)和fill()将Pixbuf复制到上下文中。可能不是最有效的方法。