2017-04-20 12 views
2

파일 선택기에서 선택한 이미지를 표시하는 작은 응용 프로그램을 만들려고합니다. 사용자가 창 크기를 조정하면 크기가 조정됩니다.이미지를 Vala의 창 크기에 맞게 조정하는 방법

내 응용 프로그램은 창 크기를 조정할 때 이미지의 크기를 조절할 수 있도록 내 클래스의 생성자에이 코드를 추가 할 때까지 작동합니다.

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에서 이미지로 변환하는 것이 너무 느린가요? 이미지를 창 크기로 조정하는 다른 방법이 있습니까?

는 어떤 도움을 주시면 감사하겠습니다 :)

답변

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 : 이 일을하면서 만약 내가 두 이미지 사이를 전환하고 확인하는 다른 버전을 만들었습니다 꽤 많은 시간과 메모리가 증가하는지 확인하지만 그렇지 않습니다. 몇 개의 Box를 추가하고 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 그냥 ur 의견을 읽으십시오. 글쎄, 그렇게 더럽지는 않지만 최선의 방법을 반영하지는 않습니다. 좋은 생각은 [eog (gnome의 눈, 기본 이미지 뷰어)] (https://github.com/GNOME/eog)에서 코드를 확인하는 것입니다. 또 다른 방법은 그림 영역을 기반으로 이미지보기 위젯을 작성하고 카이로 (예 : 크기 조정 및 이미지 그리기)를 실행하는 것입니다. 몇 가지 aproaches가 있습니다. 물론,이 하나의 작품과 향상시킬 수 있습니다. 과거에는 이와 같은 것을 구현했습니다. 심지어 전문적으로도 효과가있었습니다. –

+0

또한 원래 pixbuf를 유지하고 크기를 조정합니다. 이미지에서 pixbuf를 검색하면 축적 된 리샘플링 손실이 추가되어 이미지 품질이 저하됩니다. –