如何获得光标位置悬停在GTK-rs绘图区域?



我正在Rust中开发一个包含绘图区域的GTK-rs应用程序。每当用户在绘图区域上方悬停时,我试图将光标的位置打印到命令行。我已经尝试使用运动通知事件与回调函数,检索事件的x和y坐标使用position()方法,然后使用println!()打印到控制台。但是,当我运行应用程序并将鼠标悬停在绘图区域上时,没有任何内容打印到控制台。

下面是我使用的Rust代码:

use cairo::{ImageSurface, Context, Format};
use gtk::prelude::*;
use gtk::{Builder, Window, DrawingArea};
fn main() {
if let Err(err) = gtk::init() {
println!("Failed to initialize GTK: {}", err);
return;
}
let glade_src = include_str!("interface.ui");
let builder = Builder::from_string(glade_src);
let window: Window = builder.object("main").unwrap();
let drawing: DrawingArea = builder.object("canvas").unwrap();    

let surface = ImageSurface::create(Format::ARgb32, 600, 700).unwrap();
drawing.connect_draw(move |_,cr| {
let surface_ctx = Context::new(&surface).unwrap();
surface_ctx.set_source_rgb(1.0,1.0,1.0);
surface_ctx.paint().expect("unable to paint surface_ctx");
cr.set_source_surface(&surface, 0.0, 0.0).expect("unable to set source surface");
cr.paint().expect("unable to paint context");
Inhibit(false)
});

drawing.connect_motion_notify_event(|_widget, event| {
let x = event.position().0;
let y = event.position().1;
println!("Mouse click position: ({}, {})", x, y);
Inhibit(false)
});
window.show_all();
gtk::main();
}

interface.ui:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="main">
<property name="can-focus">False</property>
<child>
<object class="GtkPaned">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="position">400</property>
<child>
<object class="GtkDrawingArea" id="canvas">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">A scaled down version
of the interface.ui</property>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

我尝试使用button_press_event信号,motion_notify_eventdrawing.grab_focus()来捕获鼠标事件,但这些方法都不适合我。

我期望当我将鼠标悬停在绘图区域上时,我的程序会将光标的位置打印到控制台。但是,当我将鼠标悬停在绘图区域上时,没有打印任何内容。

任何关于如何使这项工作或我错过了什么建议将不胜感激。

我做了一些研究,并遇到了对类似问题的Python答案,这表明您需要设置DrawingArea以使其接收事件。因此,在代码中,您将使用gdk来设置POINTER_MOTION_MASK,如下所示:

drawing.set_events(gdk::EventMask::POINTER_MOTION_MASK);
所以你的完整程序看起来像这样:
use gtk::cairo::{ImageSurface, Context, Format};
use gtk::prelude::*;
use gtk::{Builder, Window, DrawingArea};
use gdk;
fn main() {
if let Err(err) = gtk::init() {
println!("Failed to initialize GTK: {}", err);
return;
}
let glade_src = include_str!("interface.ui");
let builder = Builder::from_string(glade_src);
let window: Window = builder.object("main").unwrap();
let drawing: DrawingArea = builder.object("canvas").unwrap();    

let surface = ImageSurface::create(Format::ARgb32, 600, 700).unwrap();
drawing.connect_draw(move |_,cr| {
let surface_ctx = Context::new(&surface).unwrap();
surface_ctx.set_source_rgb(1.0,1.0,1.0);
surface_ctx.paint().expect("unable to paint surface_ctx");
cr.set_source_surface(&surface, 0.0, 0.0).expect("unable to set source surface");
cr.paint().expect("unable to paint context");
Inhibit(false)
});
drawing.set_events(gdk::EventMask::POINTER_MOTION_MASK);
drawing.connect_motion_notify_event(|_widget, event| {
let x = event.position().0;
let y = event.position().1;
println!("Mouse click position: ({}, {})", x, y);
Inhibit(false)
});
window.show_all();
gtk::main();
}

当鼠标移动到绘图区域时,程序将输出光标位置。

最新更新