GTK-rs中按下鼠标时如何修改pixbuf?

问题描述 投票:0回答:1

我试图在单击鼠标左键时修改 pixbuf,但我认为它没有被修改。 modify_pixel 函数只是从 pixbuf 中获取特定像素并对其进行修改。

fn build_ui(application: &Application) {
    
    let pixbuf = Pixbuf::from_file("assets/map.png").expect("msg");
    let pixbuf = Rc::new(RefCell::new(pixbuf));
    
    let gesture = GestureClick::new();

    let pixbuf_clone = Rc::clone(&pixbuf);

    
    gesture.connect_pressed(move |_gesture, _n_press, x, y| {
        let mut pixbuf = pixbuf_clone.borrow_mut();
        let position = [x as usize, y as usize];
        if position[0] < pixbuf.width() as usize && position[1] < pixbuf.height() as usize {
            modify_pixel(&mut pixbuf, position);
        } else {
            println!("Out of bounds");
        }
    });

    let picture = Picture::for_pixbuf(Some(&pixbuf.borrow()).expect("No se pudo crear el Picture"));


    let window = ApplicationWindow::builder()
        .application(application)
        .default_height(800)
        .default_width(800)
        .title("My GTK App")
        .build();
    window.set_child(Some(&picture));
    window.add_controller(gesture);
    window.present();
}
fn modify_pixel(pixbuf: &mut Pixbuf, position: [usize;2]){
    let pixels = unsafe {pixbuf.pixels()};
    let rowstride = pixbuf.rowstride() as usize;
    let n_channels = pixbuf.n_channels() as usize;

    
    let offset = position[1] * rowstride + position[0] * n_channels;

    let mut pixels = pixels.to_vec(); 
    pixels[offset] = 255;  
    pixels[offset + 1] = 0;  
    pixels[offset + 2] = 0;  
    *pixbuf = Pixbuf::from_mut_slice(
        pixels,
        Colorspace::Rgb,
        pixbuf.has_alpha(),
        8, 
        pixbuf.width(),
        pixbuf.height(),
        rowstride as i32,
    );
}

我也不确定使用手势是否是最合适的选择。我尝试修改条款中的图片,但我遇到了同样的问题

rust gtk gtk-rs
1个回答
0
投票

您需要使用

set_pixbuf
来更新
Pixbuf
,如下所示:

fn build_ui(application: &Application) {
    let pixbuf = Pixbuf::from_file("assets/map.png").expect("msg");
    let pixbuf = Rc::new(RefCell::new(pixbuf));
    let pixbuf_clone = Rc::clone(&pixbuf);
    
    let gesture = GestureClick::new();

    let picture = Picture::for_pixbuf(Some(&pixbuf.borrow()).expect("Failed to load image."));

    let window = ApplicationWindow::builder()
        .application(application)
        .default_height(800)
        .default_width(800)
        .title("GTK Pixbuf test")
        .build();
    window.set_child(Some(&picture));

    gesture.connect_pressed(move |_gesture, _n_press, x, y| {
        let mut pixbuf = pixbuf_clone.borrow_mut();
        let position = [x as usize, y as usize];
        if position[0] < pixbuf.width() as usize && position[1] < pixbuf.height() as usize {
            modify_pixel(&mut pixbuf, position);
            picture.set_pixbuf(Some(&pixbuf));
        } else {
            println!("Out of bounds");
        }
    });

    window.add_controller(gesture);
    window.present();
}

用鼠标单击图像时,会将像素更改为红色。

我认为这并不完全是您想要做的,因此,我建议查看 DrawingArea 示例

顺便说一句,自 GTK v4.12 起,

Pixbuf 相关方法已被弃用。应替换为

paintable
,如下所示:

fn build_ui(application: &Application) {
    let pixbuf = Pixbuf::from_file("assets/blank.png").expect("msg");
    let pixbuf = Rc::new(RefCell::new(pixbuf));
    let pixbuf_clone = Rc::clone(&pixbuf);

    let gesture = GestureClick::new();

    let picture = Picture::for_paintable(&Texture::for_pixbuf(&pixbuf.borrow()));

    let window = ApplicationWindow::builder()
        .application(application)
        .default_height(800)
        .default_width(800)
        .title("GTK Pixbuf test")
        .build();
    window.set_child(Some(&picture));

    gesture.connect_pressed(move |_gesture, _n_press, x, y| {
        let mut pixbuf = pixbuf_clone.borrow_mut();
        let position = [x as usize, y as usize];
        if position[0] < pixbuf.width() as usize && position[1] < pixbuf.height() as usize {
            modify_pixel(&mut pixbuf, position);
            picture.set_paintable(Some(&Texture::for_pixbuf(&pixbuf)));
        } else {
            println!("Out of bounds");
        }
    });

    window.add_controller(gesture);
    window.present();
}
© www.soinside.com 2019 - 2024. All rights reserved.