我正在尝试通过在滚动窗口内的绘图区域上绘制打开的图像来在PyGTK中创建图像查看器。由于某种原因,图像不是绘图。这是观众的代码:
#!/usr/bin/env python
import gtk
import math
import time
class ImageViewerGTK:
def __init__(self):
self.filename = ""
#Set the Glade file
self.gladefile = "issue.glade"
self.builder = gtk.Builder();
self.builder.add_from_file(self.gladefile)
self.window = self.builder.get_object("window")
self.image = self.builder.get_object("image")
self.image.set_events(gtk.gdk.POINTER_MOTION_MASK)
self.builder.connect_signals(self)
self.builder.get_object("window").show_all()
self.zoom_slider = self.builder.get_object("zoomlevel")
self.constrast_slider = self.builder.get_object("contrastlevel")
self.style = self.image.get_style()
self.gc = self.style.fg_gc[gtk.STATE_NORMAL]
self.thumnail_pixmap = gtk.gdk.Pixmap(self.window.get_window(), 25, 25)
self.mouse_pressed = False
self.scroll_window = self.builder.get_object("scrolledwindow1")
self.scroll_vertical = self.scroll_window.get_vadjustment()
self.scroll_horizontal = self.scroll_window.get_hadjustment()
self.statusbar = self.builder.get_object("statusbar")
self.clickX = 0
self.clickY = 0
def on_window_destroy(self, widget, data=None):
gtk.main_quit();
def on_open_image_activate(self, menuItem, data=None):
filename = self.get_open_filename()
if filename: self.load_file(filename)
def get_open_filename(self):
filename = None
chooser = gtk.FileChooserDialog("Open File...", self.window,
gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
response = chooser.run()
if response == gtk.RESPONSE_OK: filename = chooser.get_filename()
chooser.destroy()
return filename
def load_file(self, filename):
self.filename = filename
self.clickX = 0
self.clickY = 0
self.pixbuf = gtk.gdk.pixbuf_new_from_file(self.filename)
pixmap, mask = self.pixbuf.render_pixmap_and_mask()
self.image.set_size_request(self.pixbuf.get_width(), self.pixbuf.get_height())
self.image.window.draw_drawable(self.gc, pixmap, 0, 0, 0, 0, -1, -1)
def image_motion_notify_event_cb(self, widget, event):
if self.filename != "":
pixel = self.pixbuf.get_pixels_array()[event.y][event.x]
self.statusbar.pop(3)
message = "Gray level: " + str(self.gray_level(pixel[0], pixel[1], pixel[2])) + " @ " + str(event.x) + ", " + str(event.y)
self.statusbar.push(3, message)
def gray_level(self, r, g, b):
return int(0.2126 * r + 0.7152 * g + 0.0722 * b)
if __name__ == "__main__":
try:
hwg= ImageViewerGTK()
gtk.main()
except KeyboardInterrupt:
pass
和gladefile:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkAccelGroup" id="accelgroup1"/>
<object class="GtkAction" id="action1"/>
<object class="GtkWindow" id="window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Image Viewer</property>
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="open_image">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Open a new image.</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_open_image_activate" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem9">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="imagemenuitem10">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="width_request">512</property>
<property name="height_request">512</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkDrawingArea" id="image">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
如果删除了set_size_request行,则图像会正确绘制,因此更改绘图区域大小的行为会使其无法绘制任何内容。这是为什么?
答案 0 :(得分:0)
您错误地使用了GtkDrawingArea
。绘图区域不是画布,您只能在其上绘制一次并期望系统刷新绘图;它是一个小部件,允许(并要求)您在expose
事件期间绘制它。当您需要处理图像时,这非常有用,例如:通过缩放到该区域。如果您只需要一个显示现有图像的小部件,请改用gtk.Image
。
要正确使用DrawingArea
,必须从中继承并处理expose事件。例如:
import gtk, gobject
class ImageArea(gtk.DrawingArea):
__gsignals__ = {'expose-event': 'override'}
def __init__(self, pixbuf):
super(ImageArea, self).__init__()
self._pixbuf = pixbuf
def do_expose_event(self, event):
# clip to exposed area
cr = self.window.cairo_create()
cr.rectangle(tuple(event.area))
cr.clip()
_, _, w, h = tuple(self.allocation)
# paint over the drawing context:
pb = self._pixbuf
cr.set_source_pixbuf(pb, (w - pb.get_width()) / 2, (h - pb.get_height()) / 2)
cr.paint()
gobject.type_register(ImageArea)