2011-02-08 6 views
5

Tôi có tiện ích GtkImage trong cửa sổ có thể thay đổi kích thước và tham chiếu GdkPixBuf lưu hình ảnh mà tôi muốn điền vào GtkImage.Tự động chia tỷ lệ hình ảnh theo kích thước với (Py) GTK

tôi có thể mở rộng các GdkPixBuf để điền vào widget GtkImage sử dụng phương pháp này:

def update_image(self, widget=None, data=None): 
    # Get the size of the source pixmap 
    src_width, src_height = self.current_image.get_width(), self.current_image.get_height() 

    # Get the size of the widget area 
    widget = self.builder.get_object('image') 
    allocation = widget.get_allocation() 
    dst_width, dst_height = allocation.width, allocation.height 

    # Scale preserving ratio 
    scale = min(float(dst_width)/src_width, float(dst_height)/src_height) 
    new_width = int(scale*src_width) 
    new_height = int(scale*src_height) 
    pixbuf = self.current_image.scale_simple(new_width, new_height, gtk.gdk.INTERP_BILINEAR) 

    # Put the generated pixbuf in the GtkImage widget 
    widget.set_from_pixbuf(pixbuf) 

Khi tôi gọi update_image tay nó hoạt động như mong đợi. Bây giờ tôi muốn mở rộng quy mô tự động khi tiện ích con GtkImage được thay đổi kích thước. Giải pháp tốt nhất mà tôi đưa ra là ràng buộc phương thức update_image với sự kiện configure-event GTK của cửa sổ. Sau mỗi thay đổi kích thước của cửa sổ, hình ảnh thực sự được thu nhỏ. Tuy nhiên, tôi có hai vấn đề với giải pháp này:

  • Tôi chỉ có thể làm cửa sổ lớn hơn. Khi hình ảnh đã được nâng cấp, GTK sẽ không cho phép tôi thay đổi kích thước cửa sổ nhỏ hơn vì cửa sổ không thể nhỏ hơn các tiện ích của nó. Tôi hiểu tại sao nó hoạt động như thế nhưng tôi không biết làm thế nào để thay đổi hành vi này.
  • Có thể đây không phải là vấn đề lớn nhưng tôi có thể đã ưu tiên một sự kiện từ tiện ích GtkImage thay vì cửa sổ cấp cao nhất.

Tôi xin lỗi vì lời giải thích dài về vấn đề tầm thường này, tôi hy vọng bạn sẽ có thể giúp tôi.

Trả lời

9

Tôi tin rằng bạn có thể sử dụng tín hiệu expose-event của tiện ích con để chia tỷ lệ hình ảnh. Ngoài ra, việc thêm hình ảnh vào vùng chứa có thể cuộn được sẽ khắc phục sự cố với thay đổi kích thước cửa sổ. Vui lòng kiểm tra xem một ví dụ bên dưới có phù hợp với bạn hay không.

import gtk 

class ScaleImage: 
    def __init__(self): 
     self.temp_height = 0 
     self.temp_width = 0 

     window = gtk.Window(gtk.WINDOW_TOPLEVEL) 

     image = gtk.Image() 
     image.set_from_file('/home/my_test_image.jpg') 
     self.pixbuf = image.get_pixbuf() 
     image.connect('expose-event', self.on_image_resize, window)  

     box = gtk.ScrolledWindow() 
     box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) 
     box.add(image) 

     window.add(box) 
     window.set_size_request(300, 300) 
     window.show_all()   

    def on_image_resize(self, widget, event, window): 
     allocation = widget.get_allocation() 
     if self.temp_height != allocation.height or self.temp_width != allocation.width: 
      self.temp_height = allocation.height 
      self.temp_width = allocation.width 
      pixbuf = self.pixbuf.scale_simple(allocation.width, allocation.height, gtk.gdk.INTERP_BILINEAR) 
      widget.set_from_pixbuf(pixbuf) 

    def close_application(self, widget, event, data=None): 
     gtk.main_quit() 
     return False 

if __name__ == "__main__": 
    ScaleImage() 
    gtk.main() 

hy vọng điều này giúp, coi

+1

Cảm ơn rất nhiều, thủ thuật ScrolledWindow đã hoạt động. Tôi nhận được 'GtkWarning: gtk_scrolled_window_add(): không thể thêm tiện ích con không thể cuộn gtk_scrolled_window_add_with_viewport() thay vào đó' nhưng nếu tôi thêm chế độ xem thì thanh cuộn xuất hiện khi tôi giảm kích thước cửa sổ, vì vậy tôi sẽ để nguyên nó như bây giờ. 'Expose-event' được gọi trên mỗi lần lặp gtk để nó tối đa việc sử dụng CPU. – Jim

0

Tất cả các vật dụng có size-allocate tín hiệu.

Tín hiệu "phân bổ kích thước" được phát ra khi tiện ích được cấp phân bổ không gian mới.

Có lẽ bạn có thể sử dụng điều đó.

0

Nếu bạn không muốn sử dụng GtkScrolledWindow, bạn có thể thay thế GtkImage bằng cách thay thế GtkDrawingArea và sau đó vẽ hình ảnh của bạn bằng Cairo. Điều này sẽ cho phép các hình ảnh co lại, bởi vì GtkDrawingArea không đặt yêu cầu kích thước.

Tôi không biết về Python, nhưng đây là một ví dụ trong C sử dụng GTK3:

gboolean drawing_area_draw (GtkWidget *widget, cairo_t *cr, GdkPixbuf *current_image) 
{ 

    ..... //Calculate size 

    pixbuf = gdk_pixbuf_scale_simple (current_image, 
            new_width, 
            new_height, 
            GDK_INTERP_BILINEAR); 

    gdk_cairo_set_source_pixbuf (cr, 
           pixbuf, 
           allocation.width/2 - new_width/2, 
           allocation.height/2 - new_height/2); 
    cairo_paint (cr); 

    return FALSE; 
} 

int main (int argc, char *argv[]) 
{ 
    ..... 

    drawing_area = gtk_drawing_area_new(); 
    g_signal_connect (G_OBJECT (drawing_area), "draw", 
      G_CALLBACK (drawing_area_draw), current_image); 

    ..... 
} 

Nếu nền khu vực bản vẽ xuất hiện mờ đục, thiết gtk_widget_set_has_window()-FALSE, mặc dù nó có thể là tốt hơn để lấy được của riêng bạn widget từ GtkDrawingArea và đặt thuộc tính này ở chức năng init.

Nếu bạn đang sử dụng GTK2, mã tương tự, ngoại trừ việc bạn phải gọi gdk_cairo_create() trên widget->window và gọi cairo_destroy() khi bạn hoàn tất.

Ngoài ra, với GTK2, nếu GtkDrawingArea không có GdkWindow riêng, tọa độ cho bản vẽ tương ứng với phụ huynh GdkWindow thay vì tiện ích.