python-3.x - 在 PyGtk3 中调整 Gtk.DrawingArea 的大小

标签 python-3.x gtk3 pycairo drawingarea

<分区>

请运行下面的代码得到这样的东西:

enter image description here

基本上,我已经设置了一个 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) 和图像像素强度

我面临的问题是,当您缩小足够多的次数时,图像将如下所示:

enter image description here

但是,“鼠标进入”和“鼠标离开”信号以及“鼠标移动”信号被发送,就像 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()

关于python-3.x - 在 PyGtk3 中调整 Gtk.DrawingArea 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58685222/

相关文章:

python - Python 3 中的 'function' 、 'method' 和 'bound method' 之间有什么区别?

python-3.x - Python3如何实现十六进制长除法?

python - 如何将原始二进制解码为十六进制

python - 如何使用 tkinter 和 python oop 将项目/小部件放入其他类中

python - Gio SimpleAction 调用函数

c - 获取 GTK 标签以在 C 中显示一个 int

python - 将 ARGB32 (py)cairo 表面转换为 PIL(low) 图像 - 反色?

python-3.x - Jio.MenuItem 的工具提示和信号

image - 如何使用 Pycairo 输出透明 PNG?