2017-04-20 76 views
2

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

我的应用程序工作到我将这段代码添加到我的类的构造函数,应该让图像调整窗口大小时调整大小的能力。

window.size_allocate.connect(() => { 

     resize_image(); //<-- a problem 

    }); 

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

方法resize_image()的工作原理如下:(我知道我调整大小“alogrithm”心不是最好的,但是我只是用于测试此方法)

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到图像的转换是否对用户来说太慢? 是否有另一种方法来调整图像的窗口大小?

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

回答

1

这里的窍门是添加布局和设置的调整回调不窗口,但布局。这不是完美的,它有点肮脏,但工作。初始定位工作不好,但有改进的空间。 必须检查Gtk.Widget和Gtk.Containers的请求,分配和自然大小,甚至使用Gdk方法。迟到了,希望这会让你朝正确的方向发展。

PS:我使用的是endless.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; 
} 
+0

非常感谢你:)但我有一个问题:你为什么说这是一个肮脏的方式?如果你有时间可以简单地解释如何以正确的方式来做到这一点? – guardian

+0

@guardian sry刚刚阅读你的评论。那么,不是很脏,但不反映最好的办法。一个好主意是从[eog(gnome的眼睛,默认图像查看器)](https://github.com/GNOME/eog)检查代码。另一个方法是创建一个基于绘图区域的图像视图控件,并让开罗,例如,调整大小和绘制图像。有几个问题。当然,这个工作可以改进。在过去,我已经实施了这样的事情,甚至是专业的,并且很有效。 –

+0

另外请注意,我保留原来的pixbuf并从那里调整大小。从图像中检索pixbuf会增加累积的重采样损失,并且图像质量会降低。 –