1

I'm trying to use a code in this tutorial, but the result is a grayed cell and no image in the cell (see screenshot). It's been days since I started looking for a solution to add an image to a grid cell and I find this solution the least complicated so far, but it won't work for me. Please, can someone help me with this issue so I can move on with my project? It would be greatly appreciated. Thank you.

Here is the code:

import wx
import wx.grid
class MyApp(wx.App):
    def OnInit(self):
        frame = wx.Frame(None, -1, title = "wx.Grid - Bitmap example")
        grid = wx.grid.Grid(frame)
        grid.CreateGrid(1,1)
        img = wx.Bitmap(r"E:\Dropbox2\Dropbox\Ubot\Ubot\Python\Magnify\Tkinter Magnify\Tests\python-logo.png", wx.BITMAP_TYPE_PNG)
        imageRenderer = MyImageRenderer(img)
        grid.SetCellRenderer(0,0,imageRenderer)
        grid.SetColSize(0,img.GetWidth()+2)
        grid.SetRowSize(0,img.GetHeight()+2)
        frame.Show(True)
        return True

class MyImageRenderer(wx.grid.PyGridCellRenderer):
    def __init__(self, img):
        wx.grid.PyGridCellRenderer.__init__(self)
        self.img = img
    def Draw(self, grid, attr, dc, rect, row, col, isSelected):

        image = wx.MemoryDC()
        image.SelectObject(self.img)
        dc.SetBackgroundMode(wx.SOLID)
        if isSelected:
            dc.SetBrush(wx.Brush(wx.BLUE, wx.SOLID))
            dc.SetPen(wx.Pen(wx.BLUE, 1, wx.SOLID))
        else:
            dc.SetBrush(wx.Brush(wx.WHITE, wx.SOLID))
            dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID))
        dc.DrawRectangleRect(rect)
        width, height = self.img.GetWidth(), self.img.GetHeight()
        if width > rect.width-2:
            width = rect.width-2
        if height > rect.height-2:
                height = rect.height-2
        dc.Blit(rect.x+1, rect.y+1, width, height, image, 0, 0, wx.COPY, True)

app = MyApp(0)
app.MainLoop()

And the result I get:

enter image description here

You can use this image for tests:

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Creek Barbara
  • 637
  • 1
  • 7
  • 29

2 Answers2

2

I don't know if you are running this in an IDE but if you run it on the command line, you will see all of the warnings and errors. i.e.

wxPyDeprecationWarning: Using deprecated class. Use GridCellRenderer instead.
  wx.grid.PyGridCellRenderer.__init__(self)
Traceback (most recent call last):
  File "20190519.py", line 30, in Draw
    dc.DrawRectangleRect(rect)
AttributeError: 'PaintDC' object has no attribute 'DrawRectangleRect'

Acting on these, because the example is old and outdated, we can replace PyGridCellRenderer with GridCellRenderer and dump the dc.DrawRectangleRect(rect) line altogether. if the function doesn't exist, try not using it, then look for an alternative if that doesn't work.

Edit: that line should have been dc.DrawRectangle(rect)

We end up with this:

import wx
import wx.grid
class MyApp(wx.App):
    def OnInit(self):
        frame = wx.Frame(None, -1, title = "wx.Grid - Bitmap example")
        grid = wx.grid.Grid(frame)
        grid.CreateGrid(2,2)
        img = wx.Bitmap("wxPython.jpg", wx.BITMAP_TYPE_ANY)
        imageRenderer = MyImageRenderer(img)
        grid.SetCellRenderer(0,0,imageRenderer)
        grid.SetColSize(0,img.GetWidth()+2)
        grid.SetRowSize(0,img.GetHeight()+2)
        frame.Show(True)
        return True

class MyImageRenderer(wx.grid.GridCellRenderer):
    def __init__(self, img):
        wx.grid.GridCellRenderer.__init__(self)
        self.img = img
    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
        image = wx.MemoryDC()
        image.SelectObject(self.img)
        dc.SetBackgroundMode(wx.SOLID)
        if isSelected:
            dc.SetBrush(wx.Brush(wx.BLUE, wx.SOLID))
            dc.SetPen(wx.Pen(wx.BLUE, 1, wx.SOLID))
        else:
            dc.SetBrush(wx.Brush(wx.WHITE, wx.SOLID))
            dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID))
        dc.DrawRectangle(rect)
        width, height = self.img.GetWidth(), self.img.GetHeight()
        if width > rect.width-2:
            width = rect.width-2
        if height > rect.height-2:
            height = rect.height-2
        dc.Blit(rect.x+1, rect.y+1, width, height, image, 0, 0, wx.COPY, True)

app = MyApp(0)
app.MainLoop()

Which gives us this:

enter image description here

A full set of downloadable documentation is available here: https://extras.wxpython.org/wxPython4/extras/4.0.4/wxPython-docs-4.0.4.tar.gz
The Demos are here:
https://extras.wxpython.org/wxPython4/extras/4.0.4/wxPython-demo-4.0.4.tar.gz

Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60
  • Thank you very much. It works like a charm but I still get this error in the terminal: "NotImplementedError: GridCellRenderer.GetBestSize() is abstract and must be overridden" – Creek Barbara May 19 '19 at 17:18
  • Not sure. I don't get that error. I suppose it might depend on the version you are running. I'm on wx 4.0.4 – Rolf of Saxony May 20 '19 at 08:23
0

If you got the error as below, then you probably called setlocale() directly instead of using wxLocale, creating a mismatch between the C/C++ and Windows locales.

Only change the locale by creating wxLocale objects to avoid this!

Use these two lines in the code then it will work fine:

import locale

#after created the grid

locale.setlocale(locale.LC_ALL, 'C')
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83