2014-11-25 1 views
0

스크롤 된 창 내의 그림 영역에 열린 이미지를 그려서 PyGTK에서 이미지 뷰어를 만들려고합니다. 어떤 이유로 이미지가 그려지지 않습니다.스크롤 창 안의 DrawingArea가 그려지지 않습니다.

#!/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 : 다음은 시청자에 대한 코드 년대 set_size_request 라인이 제거되면

<?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> 

이미지가 제대로립니다, 그래서 도면 영역의 크기를 변경하는 행위는 그릴이없는 렌더링 아무것도. 왜 이런거야?

+0

python3과 함께 gio.introspection을 사용하지 않는 이유는 무엇입니까? – drahnr

+0

파이썬 2.7과 Pygtk 2를 사용하고 있습니다. – aftrumpet

답변

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) 
+0

이것은 드로잉 영역에 익스포트 이벤트 핸들러를 설정하는 것과 다른 것입니까? – aftrumpet

+0

@aftrumpet 이론 상으로는 다르지는 않을지 모르지만 나는 그것을 시도하지 않았다. 'do_expose_event'를 사용하는 것은 시그널 디스패치에 의존하지 않고 위젯에 그것의 리프레쉬를 처리하기 때문에 보통 더 좋은 아이디어입니다. – user4815162342

+0

그래서 expose 이벤트를 사용해 보았습니다. 그러나 이제는 스크롤바가 조정될 때마다 이미지가 다시 그려지기 때문에 실제 스크롤 속도가 느려집니다. 이것을 막을 수있는 방법이 있습니까? – aftrumpet

관련 문제