Anzeige in Panel/StaticBitmap leeren

Plattformunabhängige GUIs mit wxWidgets.
Antworten
calo
User
Beiträge: 52
Registriert: Freitag 8. Dezember 2006, 21:35
Wohnort: Stuttgart

Hallo,

ich bin gerade dabei mir ein eigenes, kleines Snipping-Tool zu programmieren. So weit funktioniert es auch. Es macht weitgehend das was es soll. Allerdings, wenn ich ein erstes Bild mache, anschließend ein zweites kleineres, so wird das erste in dem Panel nicht gelöscht sondern das kleinere Bild einfach darüber gelegt. Ein '.ClearBackground' auf das Panel 'self.frame_grab.panel_image' scheint nicht das zu machen, was ich erwarten würde. Wenn ich aber anschließend das Bild speichere, dann wird auch das zweite Bild gespeichert. Es scheint nur ein Darstellungsfehler zu sein. Kann mir da bitte jemand auf die Sprünge helfen?

Code: Alles auswählen

import wx
from PIL import ImageGrab
import pyautogui as pag

class ImgFrame(wx.Frame):
    def __init__(self, *args, **kwds):

        kwds["style"] = kwds.get("style", 0)  | wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.STAY_ON_TOP
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((600, 400))
        self.SetTitle("Image")

        self.panel_image = wx.Panel(self, wx.ID_ANY)
        sizer_image = wx.BoxSizer(wx.VERTICAL)
        sizer_image.Add(self.panel_image, 1, wx.ALL | wx.EXPAND, 1)

        self.Layout()


class GrabFrame(wx.Frame):
    def __init__(self, *args, **kwds):

        kwds["style"] = kwds.get("style", 0)  | wx.DEFAULT_FRAME_STYLE 
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((600, 400))
        self.SetTitle("frame")

        sizer_image = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "grab image"), 
                                        wx.VERTICAL)

        self.panel_image = wx.Panel(self, wx.ID_ANY)
        sizer_image.Add(self.panel_image, 1, wx.ALL | wx.EXPAND, 1)

        sizer_bottom = wx.BoxSizer(wx.HORIZONTAL)
        sizer_image.Add(sizer_bottom, 0, wx.ALL | wx.EXPAND, 1)

        self.cmbBox_imgName = wx.ComboBox(self, wx.ID_ANY, choices=["tmp.png"], style=wx.CB_DROPDOWN | wx.CB_READONLY)
        self.cmbBox_imgName.SetSelection(0)
        sizer_bottom.Add(self.cmbBox_imgName, 1, wx.ALL, 1)

        self.btn_grab = wx.Button(self, wx.ID_ANY, "grab")
        sizer_bottom.Add(self.btn_grab, 0, 0, 0)

        self.btn_back = wx.Button(self, wx.ID_ANY, "save")
        sizer_bottom.Add(self.btn_back, 0, 0, 0)

        self.btn_cancel = wx.Button(self, wx.ID_ANY, "close")
        sizer_bottom.Add(self.btn_cancel, 0, 0, 0)

        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_image.Add(sizer_1, 0, wx.ALL | wx.EXPAND, 1)

        label_2 = wx.StaticText(self, wx.ID_ANY, "")
        sizer_1.Add(label_2, 1, wx.ALL | wx.EXPAND, 1)

        self.checkbox_1 = wx.CheckBox(self, wx.ID_ANY, "aspect-ratio active")
        self.checkbox_1.SetMinSize((140, 15))
        self.checkbox_1.SetValue(1)
        sizer_1.Add(self.checkbox_1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 1)

        label_1 = wx.StaticText(self, wx.ID_ANY, "aspect-ratio-type:   ")
        sizer_1.Add(label_1, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 1)

        self.spnCtrl_ar = wx.SpinCtrl(self, wx.ID_ANY, "1", min=1, max=6)
        self.spnCtrl_ar.SetMinSize((60, 23))
        sizer_1.Add(self.spnCtrl_ar, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 1)

        self.SetSizer(sizer_image)

        self.Layout()

        self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.checkbox_1)

    def OnCheck(self, event): 
        obj = event.GetEventObject()
        if obj.GetValue():
            self.spnCtrl_ar.Enable(True)
        else:
            self.spnCtrl_ar.Enable(False)
        event.Skip
        
class GrabApp(wx.App):
    def __init__(self, redirect=False, img_name="tmp.png"):
        self.img_name = img_name
        wx.App.__init__(self, redirect)
    
    def OnInit(self):
        self.frame_grab = GrabFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame_grab)
        self.frame_grab.Show()
        
        files = ["tmp1.png", "tmp2.png", "tmp3.png"]
        self.frame_grab.cmbBox_imgName.Clear()
        self.frame_grab.cmbBox_imgName.Insert(files, 0)
        self.frame_grab.cmbBox_imgName.SetSelection(0)
        
        self.imgframe_img = ImgFrame(None, wx.ID_ANY, "")
        self.Bind(wx.EVT_BUTTON, self.OnGrab, self.frame_grab.btn_grab)
        self.Bind(wx.EVT_BUTTON, self.OnSave, self.frame_grab.btn_back)
        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.frame_grab.btn_cancel)

        return True

    def OnSave(self, evt):
        filename = self.frame_grab.cmbBox_imgName.GetStringSelection()
        self.image.save(filename, "PNG")
        self.imgframe_img.Close()
        self.frame_grab.Close()

    def OnCancel(self, evt):
        self.imgframe_img.Close()
        self.frame_grab.Close()
        
    def OnGrab(self, evt):
        self.image = wx.Image(240, 240)
        self.imgCtrl_grab = wx.StaticBitmap(self.frame_grab.panel_image,   wx.ID_ANY, wx.Bitmap(self.image))
        self.imgCtrl_img  = wx.StaticBitmap(self.imgframe_img.panel_image, wx.ID_ANY, wx.Bitmap(self.image))
 
        self.frame_grab.Hide()
        image = ImageGrab.grab()
        w, h = image.size
        wx_image = wx.Bitmap.FromBuffer(w, h, image.tobytes())
        self.imgCtrl_img.SetBitmap(wx.Bitmap(wx_image))

        self.imgframe_img.SetSize(w, h)
        self.imgframe_img.Maximize(True)
        self.imgframe_img.panel_image.Refresh()
        self.SetTopWindow(self.imgframe_img)
        self.imgframe_img.Show()

        self.dc =  wx.ScreenDC()
        screenWidth, screenHeight = wx.DisplaySize()
        self.dc.StartDrawingOnTop(None)
        self.dc.SetPen(wx.Pen('black', 1))
        self.dc.SetBrush(wx.TRANSPARENT_BRUSH)
        self.dc.SetLogicalFunction(wx.INVERT)

        self.x, self.y, self.x_new, self.y_new = 0, 0, 0, 0 
        self.rect = wx.Rect(self.x, self.y, self.x_new, self.y_new)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
 
    def OnLeftDown(self, evt):
        self.x0, self.y0 = pag.position()

        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.Bind(wx.EVT_MOTION, self.OnMotion)

        self.rect.SetPosition((self.x0, self.y0))
        self.dc.DrawRectangle(self.rect) 
        self.imgframe_img.panel_image.Refresh()

    def OnMotion(self, evt):
        self.x_new, self.y_new = pag.position()
        self.rect.SetSize((self.x_new-self.x0, self.y_new-self.y0))
        self.rect.SetPosition((self.x0, self.y0))
        self.dc.DrawRectangle(self.rect)
        self.imgframe_img.panel_image.Refresh()

    def OnLeftUp(self, evt):
        self.x_new, self.y_new = pag.position()
        self.image = ImageGrab.grab(bbox=(self.x0, self.y0, self.x_new, self.y_new))

        # Panel-Image leeren - tut nicht was ich erwarten wuerde
        self.frame_grab.panel_image.ClearBackground()
        self.imgCtrl_grab.ClearBackground()

        w, h = self.image.size
        wx_image = wx.Bitmap.FromBuffer(w, h, self.image.tobytes())
        self.imgCtrl_grab.SetBitmap(wx.Bitmap(wx_image))
        
        if w < 600 or h < 400:
            self.frame_grab.SetSize(600, 400)
        else:
            self.frame_grab.SetSize(w+44, h+84)
        self.frame_grab.panel_image.Refresh()
        self.frame_grab.Show()
        self.imgframe_img.Hide()

        self.Unbind(wx.EVT_MOTION)
        self.Unbind(wx.EVT_LEFT_UP)
        self.Unbind(wx.EVT_LEFT_DOWN)


# #############################################################################
if __name__ == "__main__":
    
    app = GrabApp(0)
    app.MainLoop()
calo
User
Beiträge: 52
Registriert: Freitag 8. Dezember 2006, 21:35
Wohnort: Stuttgart

Hallo,

in der Zwischenzeit habe ich das Problem selber gelöst.

Die Zeilen innerhalb von 'OnGrab' habe ich nach 'OnInit' geschoben:

Code: Alles auswählen

def OnInit(self, evt):
    [...]
    self.image = wx.Image(240, 240)
    self.imgCtrl_grab = wx.StaticBitmap(self.frame_grab.panel_image,   wx.ID_ANY, wx.Bitmap(self.image))
    self.imgCtrl_img  = wx.StaticBitmap(self.imgframe_img.panel_image, wx.ID_ANY, wx.Bitmap(self.image))
    [...]
Und den '.ClearBackground()' Befehl ganz an den Anfang von 'OnGrab()':

Code: Alles auswählen

def OnGrab(self, evt):
    self.imgCtrl_grab.ClearBackground()
    [...]
Dadurch, das ich ich das Image vorher immer neu erzeugt habe (innerhalb von 'OnGrab'), ohne zuvor das alte zu löschen, hatte ich den Zugriff auf den Background verloren. Und konnte es dadurch nicht mehr löschen.
Antworten