2

我正在尝试创建一个小应用程序,它显示您在文件选择器中选择的图像。当用户调整窗口大小时,它应该调整大小。

我的应用程序一直工作到我将此代码添加到我的类的构造函数中,这应该使图像能够在调整窗口大小时调整大小。

window.size_allocate.connect(() => {

        resize_image(); //<-- a problem

    });

当窗口改变它的大小时,这个“应该”调用方法 resize_image 但是每次我添加这个代码时,我运行基本操作系统的虚拟机都会崩溃并停止工作(每次我尝试运行我的程序时都必须重新启动)。

resize_image() 方法的工作原理如下:

public void resize_image()
{
    try
    {       if(buf.get_width() < window.get_allocated_width()){
            buf = buf.scale_simple(window.get_allocated_width(), window.get_allocated_width(), Gdk.InterpType.NEAREST); 
            image.set_from_pixbuf(buf);
            }      
    }catch(Error e)
    {
    }
}

(我知道我调整大小的“算法”还不是最好的,但我只是使用这种方法进行测试。)

现在我的问题是:为什么我的程序崩溃了?从 pixbuf 到图像的转换对用户来说太慢了吗?还有另一种方法可以将图像调整为窗口大小吗?

任何帮助,将不胜感激 :)

4

1 回答 1

1

这里的技巧是添加布局并将调整大小回调设置为不是窗口而是布局。它并不完美,有点脏,但可以。初始定位效果不佳,但仍有改进空间。必须检查 Gtk.Widget 和 Gtk.Containers 的请求、分配和自然大小,甚至使用 Gdk 方法。迟到了,希望这会引导您朝着正确的方向前进。

PS:我正在使用一个无尽的.png图像,但可以随意使用另一个,只需更改代码以反映它。

using Gtk;

public int main (string[] args) {
    Gtk.Image image;
    Gtk.Layout layout;
    Gtk.Window window;
    Gdk.Pixbuf pixbuf;

    Gtk.init (ref args);

    window = new Gtk.Window ();
    layout = new Gtk.Layout (); 
    image  = new Gtk.Image ();

    try {
        pixbuf = new Gdk.Pixbuf.from_file ("endless.png");
        image = new Gtk.Image.from_pixbuf (pixbuf); 
        layout.put (image, 0,0);
        window.add (layout);

        layout.size_allocate.connect ((allocation) => {
            print ("Width: %d Height: %d\n", allocation.width, allocation.height);
            var pxb = pixbuf.scale_simple (allocation.width, allocation.height, Gdk.InterpType.BILINEAR);
            image.set_from_pixbuf (pxb);
        });

        window.destroy.connect (Gtk.main_quit);

        window.show_all ();

        Gtk.main ();

        return 0;
    } catch (Error e) {
        stderr.printf ("Could not load file...exit (%s)\n", e.message);
        return 1;
    }
}

编辑

一个简单的开罗版本:

using Gtk;
using Cairo;

public int main (string[] args) {
    Cairo.ImageSurface image;

    image = new Cairo.ImageSurface.from_png ("endless.png");

    Gtk.init (ref args);

    var window = new Gtk.Window ();
    var darea  = new DrawingArea ();
    window.add (darea);
    window.show_all ();

    darea.draw.connect ((cr) => {
        float xscale;
        float yscale;

        cr.save ();

        xscale = (float) darea.get_allocated_width () / image.get_width ();
        yscale = (float) darea.get_allocated_height () / image.get_height ();

        cr.scale (xscale, yscale);
        cr.set_source_surface (image, 0, 0);
        cr.paint ();

        cr.restore ();
        return true;
    });

    window.destroy.connect (Gtk.main_quit);

    Gtk.main ();

    return 0;
}

编辑 2:我创建了另一个版本来在 2 个图像之间切换,并检查是否在执行此操作时多次检查内存是否增加,但事实并非如此。添加了几个框,并添加了 2 个按钮。

using Gtk;
using Cairo;

public int main (string[] args) {
    Cairo.ImageSurface image;

    image = new Cairo.ImageSurface.from_png ("endless.png");

    Gtk.init (ref args);

    var window = new Gtk.Window ();
    var box1   = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); 
    var box2   = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); 
    var b1     = new Gtk.Button.with_label ("Image1");
    var b2     = new Gtk.Button.with_label ("Image2");
    box2.pack_start (b1, true, true, 0);
    box2.pack_end (b2, true, true, 0);
    var darea  = new DrawingArea ();
    box1.pack_start (box2, false, false, 0);
    box1.pack_end (darea, true, true, 0);
    window.add (box1);
    window.show_all ();

    b1.clicked.connect (() => {
        image = new Cairo.ImageSurface.from_png ("endless.png");
        darea.queue_draw ();
    });

    b2.clicked.connect (() => {
        image = new Cairo.ImageSurface.from_png ("Gnome-logo.png");
        darea.queue_draw ();
    });

    darea.draw.connect ((cr) => {
        float xscale;
        float yscale;

        cr.save ();

        xscale = (float) darea.get_allocated_width () / image.get_width ();
        yscale = (float) darea.get_allocated_height () / image.get_height ();

        cr.scale (xscale, yscale);
        cr.set_source_surface (image, 0, 0);
        cr.paint ();

        cr.restore ();
        return true;
    });

    window.destroy.connect (Gtk.main_quit);

    Gtk.main ();

    return 0;
}
于 2017-04-21T01:12:57.013 回答