1

I'm trying to display multiple cairo drawings overlapping each other:

extern crate cairo;
extern crate gio;
extern crate gtk;

use std::f64::consts::PI;

use gio::prelude::*;
use gtk::prelude::*;
use gtk::DrawingArea;

use std::env::args;

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);

    window.set_default_size(300, 300);

    let overlay = gtk::Overlay::new();

    // Draw first circle
    let drawing_area1 = Box::new(DrawingArea::new)();
    drawing_area1.connect_draw(|_, ctx| draw(ctx, 0.5, 0.4));
    overlay.add(&drawing_area1);

    // Draw second circle
    let drawing_area2 = Box::new(DrawingArea::new)();
    drawing_area2.connect_draw(|_, ctx| draw(ctx, 0.2, 1.0));
    overlay.add(&drawing_area2);

    window.add(&overlay);
    window.show_all();
}

fn draw(ctx: &cairo::Context, width: f64, color: f64) -> Inhibit {
    ctx.scale(300., 300.);

    ctx.arc(0.5, 0.5, width, 0.0 * PI, 2.0 * PI);

    ctx.set_source_rgba(color, 0.0, 0.0, 0.8);
    ctx.fill_preserve();
    Inhibit(false)
}

fn main() {
    let application =
        gtk::Application::new(Some("example.overlay"), Default::default())
            .expect("Initialization failed...");

    application.connect_activate(|app| {
        build_ui(app);
    });

    application.run(&args().collect::<Vec<_>>());
}

Running this code gives me this warning:

(test_overlay_gtk:25534): Gtk-WARNING **: 19:12:05.573: Attempting to add a widget with type GtkDrawingArea to a GtkOverlay, but as a GtkBin subclass a GtkOverlay can only contain one widget at a time; it already contains a widget of type GtkDrawingArea

I understand that the overlay object can display only one of the drawing areas. I thought the overlay class is for exactly this purpose, to show overlapping widgets. I can't find a way to display the second overlapping drawing area.

Natjo
  • 2,005
  • 29
  • 75

2 Answers2

1

add adds the widget to the overlay as the primary child - you can only have one of these. This is inherited from the container class in older versions of gtkmm (which I assume you're using) and is replaced by set_child in gtkmm 4 (which no longer inherits add from Gtk::Container).

add_overlay is the Gtk::Overlay specific method that allows you to add any number of widgets to be displayed on top of the child widget.

Try replacing your second add method with add_overlay and it should work.

0

First: I have no idea what I am doing here.

I simply asked Google for GtkOverlay and found this page: https://developer.gnome.org/gtk3/stable/GtkOverlay.html

The documentation for gtk_overlay_add_overlay says:

Adds widget to overlay.

The widget will be stacked on top of the main widget added with gtk_container_add().

So, apparently there is a main widget which you .add() and overlays which you .add_overlay().

For your example code: Can't you just draw the two drawings to the same overlay widget? Something like drawing_area1.connect_draw(|_, ctx| draw(ctx, 0.5, 0.4); draw(ctx, 0.2, 1.0));

Uli Schlachter
  • 9,337
  • 1
  • 23
  • 39