英文:
Why is this GestureMultiPress not registering my presses?
问题
我使用gtk-rs(GTK+ 3)制作了一个小应用程序,但无法注册鼠标点击事件。
我有一个DrawingArea
,我希望每次在该DrawingArea
中单击鼠标时运行一些代码。我理解可以使用GestureMultiPress
来实现这一点。(我知道事件也可以做到这一点,但我理解多重按手势也可以做到,而且我有印象它们(手势)更符合现代风格。)
这是我设置GestureMultiPress
代码的方式:
let drw_area : DrawingArea = ...;
...
window.add(&drw_area);
...
window.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK);
let press =
GestureMultiPress::builder()
.button(0)
.widget(&drw_area)
.build();
let _press_handler_id = {
press.connect_pressed(|g, npress, x, y| {
println!("({}, {npress}, {x}, {y})", g.current_button());
})
};
...
我期望这将在单击绘图区域时打印鼠标坐标,而在单击应用程序边框时不打印。但是,它根本不打印。
我在这里漏掉了什么/做错了什么?
完整的代码:
use gtk::gdk::EventMask;
use gtk::prelude::*;
use gtk::{DrawingArea, GestureMultiPress};
const APP_NAME : &'static str = "com.example.appname";
const APP_TITLE : &'static str = "Example App";
const APP_WIDTH : i32 = 600;
const APP_HEIGHT : i32 = 600;
const APP_BORDER_WIDTH : u32 = 20;
fn build_ui(application : &gtk::Application) {
let window = gtk::ApplicationWindow::new(application);
window.set_title(APP_TITLE);
window.set_border_width(APP_BORDER_WIDTH);
window.set_position(gtk::WindowPosition::Center);
window.set_default_size(APP_WIDTH, APP_HEIGHT);
let drw_area = {
DrawingArea::builder()
.width_request(APP_WIDTH - 2*APP_BORDER_WIDTH as i32)
.height_request(APP_HEIGHT - 2*APP_BORDER_WIDTH as i32)
.build()
};
drw_area.connect_draw(|a, c| {
c.set_source_rgb(0.0, 0.0, 0.0);
c.rectangle(0.0, 0.0, a.allocated_width() as f64, a.allocated_height() as f64);
let _ = c.fill();
Inhibit(false)
});
window.add(&drw_area);
window.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK);
let press =
GestureMultiPress::builder()
.button(0)
.widget(&drw_area)
.build();
let _press_handler_id = {
press.connect_pressed(|g, npress, x, y| {
println!("({}, {npress}, {x}, {y})", g.current_button());
})
};
window.show_all();
}
fn main() {
let application =
gtk::Application::new(Some(APP_NAME), Default::default());
application.connect_activate(build_ui);
application.run();
}
英文:
I'm making a small app using gtk-rs (GTK+ 3), and I can't get it to register my mouse clicks.
I have a DrawingArea
, and I want to run some code every time there's a mouse click in that DrawingArea
. My understanding is that I can use a GestureMultiPress
to do this. (I am aware events can also do this, but my understanding is that the multi-press gesture can do this too, and I had the impression that they (Gestures) are the more modern style.)
Here's how I set up the GestureMultiPress
code:
let drw_area : DrawingArea = ...;
...
window.add(&drw_area);
...
window.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK);
let press =
GestureMultiPress::builder()
.button(0)
.widget(&drw_area)
.build();
let _press_handler_id = {
press.connect_pressed(|g, npress, x, y| {
println!("({}, {npress}, {x}, {y})", g.current_button());
})
};
...
I was expecting this to print the mouse coords when I clicked/released in the drawing area, and not print when I clicked/released in the app border. However, it's not printing at all.
What am I missing / doing wrong here?
Full Code:
use gtk::gdk::EventMask;
use gtk::prelude::*;
use gtk::{DrawingArea, GestureMultiPress};
const APP_NAME : &'static str = "com.example.appname";
const APP_TITLE : &'static str = "Example App";
const APP_WIDTH : i32 = 600;
const APP_HEIGHT : i32 = 600;
const APP_BORDER_WIDTH : u32 = 20;
fn build_ui(application : &gtk::Application) {
let window = gtk::ApplicationWindow::new(application);
window.set_title(APP_TITLE);
window.set_border_width(APP_BORDER_WIDTH);
window.set_position(gtk::WindowPosition::Center);
window.set_default_size(APP_WIDTH, APP_HEIGHT);
let drw_area = {
DrawingArea::builder()
.width_request(APP_WIDTH - 2*APP_BORDER_WIDTH as i32)
.height_request(APP_HEIGHT - 2*APP_BORDER_WIDTH as i32)
.build()
};
drw_area.connect_draw(|a, c| {
c.set_source_rgb(0.0, 0.0, 0.0);
c.rectangle(0.0, 0.0, a.allocated_width() as f64, a.allocated_height() as f64);
let _ = c.fill();
Inhibit(false)
});
window.add(&drw_area);
window.add_events(EventMask::BUTTON_PRESS_MASK | EventMask::BUTTON_RELEASE_MASK);
let press =
GestureMultiPress::builder()
.button(0)
.widget(&drw_area)
.build();
let _press_handler_id = {
press.connect_pressed(|g, npress, x, y| {
println!("({}, {npress}, {x}, {y})", g.current_button());
})
};
window.show_all();
}
fn main() {
let application =
gtk::Application::new(Some(APP_NAME), Default::default());
application.connect_activate(build_ui);
application.run();
}
答案1
得分: 0
I have worked out the problem.
At the end of the scope, Rust deallocates the GestureMultiPress
because it isn't referenced anywhere.
You can tell this by leaking a reference to it so that Rust doesn't deallocate it at the end of the scope.
let a = Rc::new(press);
mem::forget(a.clone());
I'm not sure how to actually keep the gesture around properly, given it's allocated inside a function with a fixed signature, so I can't pass things out; but that's a different question.
英文:
I have worked out the problem.
At the end of the scope, Rust deallocates the GestureMultiPress
because it isn't referenced anywhere.
You can tell this by leaking a reference to it so that Rust doesn't deallocate it at the end of the scope.
let a = Rc::new(press);
mem::forget(a.clone());
I'm not sure how to actually keep the gesture around properly, given it's allocated inside a function with a fixed signature, so I can't pass things out; but that's a different question.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论