在 PyGtk3 中调整 Gtk.DrawingArea 的大小
Resizing a Gtk.DrawingArea in PyGtk3
请运行下面的代码来得到这样的东西:
基本上,我设置了一个 Gtk.DrawingArea,它在 Gtk.Viewport 中,它也在 Gtk.Scrolledwindow 中。在所述 DrawingArea 中,我绘制了一个图像,并使用 2 个按钮可以缩放该图像。
# -*- encoding: utf-8 -*-
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GdkPixbuf
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="DrawingTool")
self.set_default_size(800, 600)
# The ratio
self.ratio = 1.
# Image
filename = "image.jpg"
self.original_image = GdkPixbuf.Pixbuf.new_from_file(filename)
self.displayed_image = GdkPixbuf.Pixbuf.new_from_file(filename)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
# Zoom buttons
self.button_zoom_in = Gtk.Button(label="Zoom-In")
self.button_zoom_out = Gtk.Button(label="Zoom-Out")
# |ScrolledWindow
# |-> Viewport
# |--> DrawingArea
scrolledwindow = Gtk.ScrolledWindow()
viewport = Gtk.Viewport()
self.drawing_area = Gtk.DrawingArea()
self.drawing_area.set_size_request(
self.displayed_image.get_width(), self.displayed_image.get_height())
self.drawing_area.set_events(Gdk.EventMask.ALL_EVENTS_MASK)
# Pack
viewport.add(self.drawing_area)
scrolledwindow.add(viewport)
box.pack_start(self.button_zoom_in, False, True, 0)
box.pack_start(self.button_zoom_out, False, True, 0)
box.pack_start(scrolledwindow, True, True, 0)
self.add(box)
# Connect
self.connect("destroy", Gtk.main_quit)
self.button_zoom_in.connect("clicked", self.on_button_zoom_in_clicked)
self.button_zoom_out.connect("clicked", self.on_button_zoom_out_clicked)
self.drawing_area.connect("enter-notify-event", self.on_drawing_area_mouse_enter)
self.drawing_area.connect("leave-notify-event", self.on_drawing_area_mouse_leave)
self.drawing_area.connect("motion-notify-event", self.on_drawing_area_mouse_motion)
self.drawing_area.connect("draw", self.on_drawing_area_draw)
self.show_all()
def on_button_zoom_in_clicked(self, widget):
self.ratio += 0.1
self.scale_image()
self.drawing_area.queue_draw()
def on_button_zoom_out_clicked(self, widget):
self.ratio -= 0.1
self.scale_image()
self.drawing_area.queue_draw()
def scale_image(self):
self.displayed_image = self.original_image.scale_simple(self.original_image.get_width() * self.ratio,
self.original_image.get_height() * self.ratio, 2)
def on_drawing_area_draw(self, drawable, cairo_context):
pixbuf = self.displayed_image
self.drawing_area.set_size_request(pixbuf.get_width(), pixbuf.get_height())
Gdk.cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0)
cairo_context.paint()
def on_drawing_area_mouse_enter(self, widget, event):
print("In - DrawingArea")
def on_drawing_area_mouse_leave(self, widget, event):
print("Out - DrawingArea")
def on_drawing_area_mouse_motion(self, widget, event):
(x, y) = int(event.x), int(event.y)
offset = ( (y*self.displayed_image.get_rowstride()) +
(x*self.displayed_image.get_n_channels()) )
pixel_intensity = self.displayed_image.get_pixels()[offset]
print("(" + str(x) + ", " + str(y) + ") = " + str(pixel_intensity))
MyWindow()
Gtk.main()
运行 应用程序。我还设置了一些回调,所以当你将鼠标指针悬停在图像上时,你会知道:
i) 当你进入绘图区
ii) 当你离开绘图区时
iii) DrawingArea处的(x,y)和图像像素强度
我面临的问题是,当你缩小足够多的时候,图像会是这样的:
然而,'mouse enter' 和 'mouse leave' 信号以及 'mouse motion' 信号被发送,就像 DrawingArea 仍然具有与创建时相同的大小。请将鼠标悬停在图像上和图像外但在 DrawingArea 内以查看终端中的输出。
我希望信号在悬停在图像外时不要自行发送。即,如果可能,将 DrawingArea 大小调整为显示的图像大小。
我使用了 gtk_window_resize(),因为它在这里提到:Cannot reduce size of gtk window programatically
def on_drawing_area_draw(self, drawable, cairo_context):
pixbuf = self.displayed_image
# New line. Get DrawingArea's window and resize it.
drawable.get_window().resize(pixbuf.get_width(), pixbuf.get_height())
drawable.set_size_request(pixbuf.get_width(), pixbuf.get_height())
Gdk.cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0)
cairo_context.paint()
请运行下面的代码来得到这样的东西:
基本上,我设置了一个 Gtk.DrawingArea,它在 Gtk.Viewport 中,它也在 Gtk.Scrolledwindow 中。在所述 DrawingArea 中,我绘制了一个图像,并使用 2 个按钮可以缩放该图像。
# -*- encoding: utf-8 -*-
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GdkPixbuf
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="DrawingTool")
self.set_default_size(800, 600)
# The ratio
self.ratio = 1.
# Image
filename = "image.jpg"
self.original_image = GdkPixbuf.Pixbuf.new_from_file(filename)
self.displayed_image = GdkPixbuf.Pixbuf.new_from_file(filename)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
# Zoom buttons
self.button_zoom_in = Gtk.Button(label="Zoom-In")
self.button_zoom_out = Gtk.Button(label="Zoom-Out")
# |ScrolledWindow
# |-> Viewport
# |--> DrawingArea
scrolledwindow = Gtk.ScrolledWindow()
viewport = Gtk.Viewport()
self.drawing_area = Gtk.DrawingArea()
self.drawing_area.set_size_request(
self.displayed_image.get_width(), self.displayed_image.get_height())
self.drawing_area.set_events(Gdk.EventMask.ALL_EVENTS_MASK)
# Pack
viewport.add(self.drawing_area)
scrolledwindow.add(viewport)
box.pack_start(self.button_zoom_in, False, True, 0)
box.pack_start(self.button_zoom_out, False, True, 0)
box.pack_start(scrolledwindow, True, True, 0)
self.add(box)
# Connect
self.connect("destroy", Gtk.main_quit)
self.button_zoom_in.connect("clicked", self.on_button_zoom_in_clicked)
self.button_zoom_out.connect("clicked", self.on_button_zoom_out_clicked)
self.drawing_area.connect("enter-notify-event", self.on_drawing_area_mouse_enter)
self.drawing_area.connect("leave-notify-event", self.on_drawing_area_mouse_leave)
self.drawing_area.connect("motion-notify-event", self.on_drawing_area_mouse_motion)
self.drawing_area.connect("draw", self.on_drawing_area_draw)
self.show_all()
def on_button_zoom_in_clicked(self, widget):
self.ratio += 0.1
self.scale_image()
self.drawing_area.queue_draw()
def on_button_zoom_out_clicked(self, widget):
self.ratio -= 0.1
self.scale_image()
self.drawing_area.queue_draw()
def scale_image(self):
self.displayed_image = self.original_image.scale_simple(self.original_image.get_width() * self.ratio,
self.original_image.get_height() * self.ratio, 2)
def on_drawing_area_draw(self, drawable, cairo_context):
pixbuf = self.displayed_image
self.drawing_area.set_size_request(pixbuf.get_width(), pixbuf.get_height())
Gdk.cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0)
cairo_context.paint()
def on_drawing_area_mouse_enter(self, widget, event):
print("In - DrawingArea")
def on_drawing_area_mouse_leave(self, widget, event):
print("Out - DrawingArea")
def on_drawing_area_mouse_motion(self, widget, event):
(x, y) = int(event.x), int(event.y)
offset = ( (y*self.displayed_image.get_rowstride()) +
(x*self.displayed_image.get_n_channels()) )
pixel_intensity = self.displayed_image.get_pixels()[offset]
print("(" + str(x) + ", " + str(y) + ") = " + str(pixel_intensity))
MyWindow()
Gtk.main()
运行 应用程序。我还设置了一些回调,所以当你将鼠标指针悬停在图像上时,你会知道:
i) 当你进入绘图区
ii) 当你离开绘图区时
iii) DrawingArea处的(x,y)和图像像素强度
我面临的问题是,当你缩小足够多的时候,图像会是这样的:
然而,'mouse enter' 和 'mouse leave' 信号以及 'mouse motion' 信号被发送,就像 DrawingArea 仍然具有与创建时相同的大小。请将鼠标悬停在图像上和图像外但在 DrawingArea 内以查看终端中的输出。
我希望信号在悬停在图像外时不要自行发送。即,如果可能,将 DrawingArea 大小调整为显示的图像大小。
我使用了 gtk_window_resize(),因为它在这里提到:Cannot reduce size of gtk window programatically
def on_drawing_area_draw(self, drawable, cairo_context):
pixbuf = self.displayed_image
# New line. Get DrawingArea's window and resize it.
drawable.get_window().resize(pixbuf.get_width(), pixbuf.get_height())
drawable.set_size_request(pixbuf.get_width(), pixbuf.get_height())
Gdk.cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0)
cairo_context.paint()