GTK4 Проблема с установкой изображения из pixbuf с помощью GtkDropTarget

Я тестирую виджет gtk4, который называется GtkDropTarget. Я планирую установить изображение, которое перетаскивается в окно, как изображение самого окна. Но ошибки возникают, как только я перетаскиваю файл изображения. Для ясности, это код в vala:

      int main (string[] args) {
    var app = new App();
    return app.run(args);
}

public class App : Gtk.Application {
    public App () {
    Object (
        application_id: "com.github.ea",
        flags: ApplicationFlags.FLAGS_NONE
    );
    }
    public override void activate () {
    var window = new Window (this);
    add_window (window);
    }
}

public class Window : Gtk.ApplicationWindow {
    public Window (Gtk.Application app) {
        Object (application: app);
    }

construct {
        title = "Drag";
    set_default_size (640, 480);
    var drag_source = new DragSource ();
    set_child (drag_source.self);       
    show ();
    }
}

public class DragSource {
    public Gtk.Image self;

    public DragSource () {

        self = new Gtk.Image ();
        var drag_controller = new Gtk.DropTarget (GLib.Type.INVALID,     Gdk.DragAction.COPY);

        drag_controller.set_gtypes ({typeof(File)});

        self.add_controller (drag_controller);
        drag_controller.on_drop.connect (on_drop);
    }

    private bool on_drop (GLib.Value val, double x, double y) {
        File filename = (File) val;
        var file_path = filename.get_path ();
        
        if (val.holds(typeof(File)) == true) {
        print ("The dragged object is a file.\n");

        if ("png" in file_path || "jpg" in file_path) {
                print ("The dragged object is an image.\n");
                self.set_from_pixbuf (pixbuf(file_path));
        }
            else {
                print ("The dragged object is NOT an image.\n");
        }
    }
        else {
            print ("The dragged object is NOT a file.\n");
        return false;
        }
        return true;
    }

    private Gdk.Pixbuf pixbuf (string file) {
        try {
            return new Gdk.Pixbuf.from_file (file);
        } catch (Error e) {
            error ("%s", e.message);
            }
        }
}

This compiles and runs. But as soon as I drag an image file to the window, error occurs and the image is not displayed. This are the pictures of what happens. What should happen is, when I drag a png file from my file manager, the dragged image should be the image showing in the GtkImage, which is the main widget of the window.

On my first drag of an image file from my pc, this error shows up:

      The dragged object is a file.
The dragged object is an image.

(v:3891): Gtk-CRITICAL **: 08:52:28.861: gtk_image_set_from_pixbuf: assertion 'GTK_IS_IMAGE (image)' failed

On the second drag, this shows up:

      (v:3891): Gdk-CRITICAL **: 08:53:33.388: gdk_drop_set_actions: assertion 'priv->state == GDK_DROP_STATE_NONE' failed
The dragged object is a file.
The dragged object is an image.

(v:3891): Gtk-CRITICAL **: 08:53:33.973: gtk_image_set_from_pixbuf: assertion 'GTK_IS_IMAGE (image)' failed

I would really appreciate a help. Thank You!

1 ответ

Вот как бы я реализовал твое намерение

      int main (string[] args) {
    var app = new App ();
    return app.run (args);
}

public class App : Gtk.Application {
    public App () {
        Object (
            application_id: "com.github.ea",
            flags : ApplicationFlags.FLAGS_NONE
        );
    }

    public override void activate () {
        var window = new Window (this);
        window.present ();
    }
}

public class Window : Gtk.ApplicationWindow {
    public Window (Gtk.Application app) {
        Object (application: app);
    }

    construct {
        title = "Drag an Image!";
        set_default_size (640, 480);

        var image = new Gtk.Image ();
        image.vexpand = image.hexpand = true;

        var controller = new Gtk.DropTarget (typeof (GLib.File), Gdk.DragAction.COPY);
        controller.on_drop.connect ((target, value, x, y) => {
            var file = (GLib.File) value;
            var filename = file.get_path ();
            if (GLib.ContentType.guess (filename, null, null).contains ("image")) {
                image.set_from_file (filename);
            }
        });
        image.add_controller (controller);

        set_child (image);
    }
}
Другие вопросы по тегам