るいもの戯れ言
#130
2017/01/13 11:41

gtk-rs研究の続き。今回は、画像を重ねてみる。やりたいことは、こういう画像と:

こういう画像とを重ねて:

こういう表示をしたい。

複数の画像の描画は、前回の記事の方法でも行える。


drawingArea.connect_draw(move |widget, context| {
    context.set_source_pixbuf(&pix1, 0f64, 0f64);
    context.paint();
    context.set_source_pixbuf(&pix2, 0f64, 0f64);
    context.paint();
    return Inhibit(false);
});

こんな感じで複数のPixbufを、set_source_pixbuf()してpaint()していけば良い。しかし、これだとdrawの度に描画が起きるため、数が増えていくとパフォーマンスに影響したり、ちらついたりするだろう。GTK+では、こういう時はSurfaceを使うようだ。


// Pixbuf(ト、ヘ音記号部分)
let clefpix = match Pixbuf::new_from_file("images/clefsImage.gif") {
    Err(e) => {
        println!("Err: {}.", e);
        return;
    }
    Ok(p) => p
};
// Pixbuf(#記号)
let sharppix = match Pixbuf::new_from_file("images/sharp.gif") {
    Err(e) => {
        println!("Err: {}.", e);
        return;
    }
    Ok(p) => p
};

// オフスクリーンバッファとして、ImageSurfaceを用意。
let isf = ImageSurface::create(Format::Rgb24, clefpix.get_width(), clefpix.get_height());

// Contextを生成して、
let ctx = Context::new(&isf);

// 描画
ctx.set_source_pixbuf(&clefpix, 0f64, 0f64);
ctx.paint();
ctx.set_source_pixbuf(&sharppix, 100f64, 100f64);
ctx.paint();

// 最後にflush()が必要のようだ。
isf.flush();

これで描画済のImageSurfaceが出来あがるので、drawの中では、これを描画すれば良い(ws.surfaceが上で作ったImageSurface)。


let ws = windowState.clone();
windowState.drawingArea.connect_draw(move |widget, context| {
    context.set_source_surface(&ws.surface, 0f64, 0f64);
    context.paint();
    return Inhibit(false);
});

できた。

サンプルコード全体は、GitHubに置いておいた。