wxPython GenStaticBitmap does not SetBitmap() when setting a bitmap from a list

51 Views Asked by At

I am building a wxPython app that acts like a drawing application and has redo/undo (ctrl+z, ctrl+y) functionality which is currently not working. I am using the GenStaticBitmap to remove flickering in my bitmap which is the solution I found here: https://discuss.wxpython.org/t/staticbitmap-fast-refresh-state-of-the-art/36197. The GenStaticBitmap is binded to all of mouse events (click, mouse events, release) to take care of drawing to genstaticbitmap. It works perfect when drawing. I use wx.MemoryDC to draw on the bitmap. I have two lists that take care of the redo/undo functionality: "redo_list and undo_list". Whenever i release my left mouse button and draw to bitmap, for example I do:

if len(self.redo_list) > 0:
            self.redo_list.clear()

        self.undo_list.append(self.genstaticbitmap.GetBitmap())
        self.undo_list_index += 1

And the part where my code is not working, i.e not drawing to my genstaticbitmap, is in these two functions:

def editRedo(self, e : wx.EVT_MENU):
        if len(self.redo_list) > 0:
            bmp : wx.Bitmap= self.redo_list.pop()

            self.undo_list.append(bmp)
            self.undo_list_index += 1

            sizeNeeded : wx.Size = wx.Size(self.realMagnifyVal * int(self.x_totalSize), self.realMagnifyVal * int(self.y_totalSize))
            wx.Bitmap.Rescale(bmp, sizeNeeded)

            self.bitmapForMap = bmp
            self.genstaticbitmap.SetBitmap(self.bitmapForMap)
            self.bitmapForMap = self.genstaticbitmap.GetBitmap()

            print("editRedo")

def editUndo(self, e : wx.EVT_MENU):
        if len(self.undo_list) > 1:
            removedItem = self.undo_list.pop(self.undo_list_index)

            self.redo_list.append(removedItem)

            self.undo_list_index -= 1
            tempBmp : wx.Bitmap = self.undo_list[self.undo_list_index]

            sizeNeeded : wx.Size = wx.Size(self.realMagnifyVal * int(self.x_totalSize), self.realMagnifyVal * int(self.y_totalSize))
            
            wx.Bitmap.Rescale(tempBmp, sizeNeeded)

            self.bitmapForMap = tempBmp
            self.genstaticbitmap.SetBitmap(self.bitmapForMap)
            self.bitmapForMap = self.genstaticbitmap.GetBitmap()
            print("editUndo")

Note that the functions editRedo and editUndo are binded to two menu items in my menu. When executing the code I see "editUndo" and "editRedo" printed on terminal, but does not set bitmap on genstaticbitmap. I used to use a wx.StaticBitmap instead of a wx.lib.statbmp.GenStaticBitmap and my redo/undo functionality worked completely. But using a wx.StaticBitmap gives me an intolerable amount of flickering when drawing. It worked correctly with staticbitmap, and I know it is obtaining bitmap data using genstaticbitmap.GetBitmap() because when printing the list while running the program, the bitmaps are there. Moreover, my application saves the image to the computer as a PNG correctly, and gets the bitmap using genstaticbitmap.GetBitmap().

Here is an example of the when the application draws to the genstaticbitmap correctly when drawing to bitmap when executing a wx.MouseEvent:

def on_clic(self, event : wx.MouseEvent):
        x, y = event.GetPosition()
        selectedColor = self.getColorLeftRightClick(evt=event)
        
        dc = wx.MemoryDC(self.bitmapForMap)
        if(self.magnifyVal > 0):
        #For when self.MagnifyVal > 1, then need to draw a rectangle which would be the same as a point for a rescaled bitmap.
            width2 = self.realMagnifyVal
            height2 = self.realMagnifyVal
            dc.SetBrush(wx.Brush(selectedColor))
            dc.SetPen(wx.Pen(selectedColor, style=wx.PENSTYLE_SOLID))
            dc.DrawRectangle(x, y, width2, height2)
        else:
            dc.SetPen(wx.Pen(selectedColor, style=wx.PENSTYLE_SOLID))
            point = wx.Point(x, y)
            dc.DrawPoint(point)

        dc.SelectObject(wx.NullBitmap)
        self.genstaticbitmap.SetBitmap(self.bitmapForMap)

        global drawBool
        drawBool = True
        event.Skip()

In my editUndo and editRedo functions I have tried to use dc.MemoryDC to use the .Clear() method and then the .DrawBitmap() method at position (0,0) to set the bitmap instead but it does not draw the corresponding bitmap at all, it ends up just clearing my genstaticbitmap. Also, I have tried to override the wx.EVT_ERASE_BACKGROUND event from the genStaticBitmap which is purposefully empty to remove flickering, and I would try to .SetBitmap() the genstaticbitmap inside there but it does not work. it would only execute inside the wx.EVT_ERASE_BACKGROUND event because I had a global variable bool which would set to true only when editUnod and editRedo is called. It would call the event correctly because it would print to the terminal when the bool is true, but it doesnt set the bitmap.

0

There are 0 best solutions below