Python 使用(Py)GTK调整大小时自动缩放图像
我在一个可调整大小的窗口中有一个Python 使用(Py)GTK调整大小时自动缩放图像,python,gtk,pygtk,Python,Gtk,Pygtk,我在一个可调整大小的窗口中有一个GtkImage小部件和一个参考GdkPixBuf存储了我想要填充GtkImage的图像 我可以使用以下方法缩放GdkPixBuf以填充GtkImage小部件: 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.
GtkImage
小部件和一个参考GdkPixBuf
存储了我想要填充GtkImage
的图像
我可以使用以下方法缩放GdkPixBuf
以填充GtkImage
小部件:
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)
当我手动调用update_image
时,它会按预期工作。现在,我希望在调整GtkImage小部件的大小时自动进行缩放。我提供的最佳解决方案是将update_image
方法绑定到窗口的configure event
GTK事件。在每次改变窗口大小后,图像确实被正确缩放。但是,此解决方案有两个问题:
- 我只能把窗户弄大些。一旦图像被放大,GTK将不允许我将窗口调整得更小,因为窗口不能小于它的小部件。我理解为什么会这样,但我不知道如何改变这种行为
- 也许这没什么大不了的,但我更喜欢GtkImage小部件中的事件,而不是顶级窗口
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()
希望这有帮助,因为所有的小部件都有(cf.)信号
当小部件获得新的空间分配时,会发出“大小分配”信号
也许你可以使用它。如果你不想使用
gtkscrolledwindowo
,你可以用gtkdrawingara
代替你的GtkImage
,然后用Cairo绘制你的图像。这将允许图像缩小,因为GtkDrawingArea
未设置大小请求
我不了解Python,但下面是一个使用GTK3的C示例:
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);
.....
}
如果绘图区域的背景看起来不透明,请将gtk_widget\u set_has_window()
设置为FALSE
,不过最好从gtkdrawingara
派生您自己的小部件,并在其init
函数中设置此属性
如果您使用的是GTK2,代码与之类似,只是您必须在widget->window
上调用gdk\u cairo\u create()
,并在完成后调用cairo\u destroy()
此外,使用GTK2,如果
GtkDrawingArea
没有自己的GdkWindow
,则绘制坐标相对于父GdkWindow
,而不是小部件。非常感谢,滚动窗口技巧起到了作用。我得到了一个GtkWarning:gtk_scrolled_window_add():无法添加不可滚动的小部件使用gtk_scrolled_window_add_with_viewport()代替
,但是如果我添加了一个视口,那么当我减小窗口大小时会出现滚动条,所以我现在就不做了。每次gtk迭代都会调用expose事件
,因此它会最大限度地提高cpu使用率。这个答案似乎在gtk+3中过时了:我以前在C中使用了“configure event”
信号,但在这方面没有正常工作。现在有了“大小分配”
我就没有问题了。