在Python中,如何在用户交互之后从模块中的类传递pixbuf

2024-09-28 22:37:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个python模块来处理屏幕截图。如果单独使用,模块本身也可以正常工作。但是,当我把它导入到我的主项目中时,我不知道如何在等待用户选择要捕获的区域之后返回一个pixbuf。 以下是屏幕截图模块:

class CaptureRegion():
def __init__(self):
    self.ThePic = None
    self.drawArea = Gtk.DrawingArea()
    self.drawArea.connect('draw',self.onDraw)
    mBox = Gtk.VBox(False,2) 
    mBox.pack_start(self.drawArea,True,True,2)
    self.MaskWin = Gtk.Window()
    self.MaskWin.set_position(Gtk.WindowPosition.CENTER)
    self.MaskWin.connect("key-press-event", self.KeyPress)
    self.MaskWin.connect("button-press-event", self.ButtonPress)
    self.MaskWin.connect("button-release-event", self.ButtonRelease)
    self.MaskWin.connect("motion-notify-event", self.Motion)
    self.MaskWin.add(mBox)

    self.button_x = 0
    self.button_y = 0
    self.button_down = False
    self.sel_rect = Gdk.Rectangle(-10, -10, 10, 10)

    self.capfull = CaptureScreen() 
    self.fullpixbuf = self.capfull.Go()

def onDraw(self, widget, event):
    print("Draw")
    myGdkWindow = self.MaskWin.get_window()
    self.cr = Gdk.cairo_create(myGdkWindow)

    self.cr.set_operator(cairo.OPERATOR_SOURCE)
    self.cr.set_source_rgb(1,1,1)
    Gdk.cairo_set_source_pixbuf(self.cr, self.fullpixbuf, 5, 5)
    self.cr.paint()

    self.cr.set_line_width(1)
    self.cr.set_source_rgb(0,0,0)


    if self.button_down == True:

        x = self.sel_rect.x
        y = self.sel_rect.y
        w = self.sel_rect.width
        h = self.sel_rect.height

        if w <= 0 or h <= 0:
            return True

        self.cr.rectangle(x,y,w,h)
        self.cr.set_source_rgba(0.2, 0.6, 0.8, 0.35)
        self.cr.set_line_width(2)
        self.cr.stroke()
    return True

def Motion(self,widget,event):
    if self.button_down == False:
        return False
    x1,y1 = self.button_x, self.button_y
    x2,y2 = event.x, event.y
    x = int(min(x1,x2))
    y = int(min(y1,y2))
    w = int(abs(x1-x2))
    h = int(abs(y1-y2))
    old = self.sel_rect
    self.sel_rect.x = x
    self.sel_rect.y = y
    self.sel_rect.width = w
    self.sel_rect.height = h

    win = self.MaskWin.get_window()
    sx, sy, sw, sh = self.MaskWin.get_window().get_geometry()
    self.drawArea.queue_draw_area(sx,sy,sw,sh)

def ButtonPress(self,widget,event):
    if not event.button == 1:
        return False
    print("button down")
    self.debounce = 0
    self.button_x, self.button_y = event.x, event.y
    self.button_down = True

    return True

def ButtonRelease(self,widget,event):
    self.button_down = False
    x = self.sel_rect.x
    y = self.sel_rect.y
    w = self.sel_rect.width
    h = self.sel_rect.height
    self.drawArea.queue_draw_area(x-1, y-1, w-1, h-1)
    if self.debounce == 0:
        self.debounce += 1
        print("Snipping x:%s y:%s w:%s h:%s" %(x,y,w,h))
        self.ThePic = Gdk.pixbuf_get_from_window(self.MaskWin.get_window(), x, y, w, h)
        self.MaskWin.hide()

        #option 2:    to return ThePic here after the selection is made thru a callback to a function in the main class 
        # i.e.
        #self.CallbackInMain(self.ThePic)    (not sure how to callback to the main class, self is wrong maybe?)


def KeyPress(self,widget,event):
    if event.keyval == Gdk.KEY_Escape:
        self.ThePic = None
        return

def WaitThread(self):
    for i in range(1, 50):
            time.sleep(0.1)
            print(i)
    self.done_waiting.set() 


def Go(self):
    self.MaskWin.fullscreen()
    self.MaskWin.show_all()
    self.MaskWin.set_decorated(False)

    #option 1 find a way to wait for the selection to complete like this:  
    #(this code doesnt end, the self.done_waiting.set() call doesnt stop it)
    # self.done_waiting = threading.Event()
    # self.thread = threading.Thread(target=self.WaitThread)
    # self.thread.start()
    # self.done_waiting.wait(1)
    # print("Main thread is done waiting")
    return(self.ThePic)
class CaptureScreen():  
def __init__(self):
    self.ThePic = None

def Go(self):
    screen = Gdk.get_default_root_window()
    x, y, width, height = screen.get_geometry()
    self.fullpixbuf = Gdk.pixbuf_get_from_window(screen, x, y, width, height)
    return(self.fullpixbuf)

我这样称呼全班同学:

import Screentshot as Shot
self.captureregion = Shot.CaptureRegion()
pic = self.captureregion.Go()
pic.savev("region.png",'png',(),())

使用CaptureScreen类,我只是捕获整个屏幕,所以我可以直接从CaptureScreen.Go()函数返回pixbuf。但是对于CaptureRegion类,我必须等待用户选择一个区域,我不知道如何让CaptureRegion.Go()在用户选择之后返回pixbuf。我有两个想法,一个是使用线程来等待选择完成,然后从Capture Region.Go()返回pixbuf(代码中的选项1),另一个是使用屏幕截图类回调函数在main中使用pixbuf作为参数(代码中的选项2)

我不太熟悉类,也没有使用过线程模块。我搜索并找到了很多信息,我只是不太明白我需要做什么


Tags: rectselfeventfalsetruegetreturndef
1条回答
网友
1楼 · 发布于 2024-09-28 22:37:12

当然,现在我终于发布了一个关于这个的问题,我想出来了。我只需要添加第二个arg to Go(self,mainself)并回调主代码中的函数

这就是我所改变的:

def ButtonRelease(self,widget,event):
    self.button_down = False
    x = self.sel_rect.x
    y = self.sel_rect.y
    w = self.sel_rect.width
    h = self.sel_rect.height
    self.drawArea.queue_draw_area(x-1, y-1, w-1, h-1)
    if self.debounce == 0:
        self.debounce += 1
        print("Snipping x:%s y:%s w:%s h:%s" %(x,y,w,h))
        self.ThePic = Gdk.pixbuf_get_from_window(self.MaskWin.get_window(), x, y, w, h)
        self.MaskWin.hide()

        self.GotTheShot = True
        self.mainself.ScreenShotCallBack(self.ThePic)

def Go(self,main):
    self.mainself = main
    self.GotTheShot = False
    self.MaskWin.fullscreen()
    self.MaskWin.show_all()
    self.MaskWin.set_decorated(False)

这是呼叫和回拨:

def ScreenShotRegion(self):
    pic = self.captureregion.Go(self)# self,mainself... self passed by default
    pic.savev("region.png",'png',(),())

def ScreenShotCallBack(self,capturepixbuf):
    self.window.show_all()
    capturepixbuf.savev("region.png",'png',(),())

相关问题 更多 >