Как передать pixbuf из класса в модуле после взаимодействия с пользователем в Python - PullRequest
0 голосов
/ 01 декабря 2018

Я работаю над модулем 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 я просто захватываю весь экран, чтобы я мог вернуть pixbuf непосредственно изФункция CaptureScreen.Go ().однако с классом CaptureRegion я должен ждать, пока пользователь выберет область, и я не уверен, как заставить CaptureRegion.Go () возвращать pixbuf после выбора пользователей.У меня есть две идеи, одна - использовать многопоточность, чтобы дождаться завершения выделения, а затем вернуть pixbuf из Capture Region.Go () (опция 1 в коде), или вторая - каким-то образом вызвать функцию обратного вызова класса снимка экрана для функции main с pixbuf какarg (вариант 2 в коде)

Я не очень знаком с классами, и я никогда не использовал модуль потоков.Я искал и нашел много информации, я просто не могу обернуть голову вокруг того, что мне нужно сделать.

1 Ответ

0 голосов
/ 02 декабря 2018

Конечно, теперь, когда я наконец-то опубликовал вопрос об этом, я понял это.мне просто нужно было добавить второй аргумент в 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',(),())
...