滚动窗口内的DrawingArea无法绘制

时间:2014-11-25 16:06:26

标签: python gtk pygtk glade

我正在尝试通过在滚动窗口内的绘图区域上绘制打开的图像来在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行,则图像会正确绘制,因此更改绘图区域大小的行为会使其无法绘制任何内容。这是为什么?

1 个答案:

答案 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)
相关问题