Creating a custom cursor

I’m using the example from the following URL to create a custom cursor

https://docs.wxpython.org/wx.Cursor.html

The following versions are installed om my machine

“”"
‘4.0.7 gtk3 (phoenix) wxWidgets 3.0.5’
Python 3.10.6
“”"

When I run the example, the following error occurs:

TypeError: Cursor(): arguments did not match any overloaded call:
overload 1: too many arguments
overload 2: argument 1 has unexpected type ‘list’
overload 3: argument 1 has unexpected type ‘list’
overload 4: argument 1 has unexpected type ‘list’
overload 5: argument 1 has unexpected type ‘list’

This is understandable.
The example contains the following code to create the cursor object.
down_cursor = wx.Cursor(down_bits, 32, 32, 6, 14, down_mask, wx.WHITE, wx.BLACK)
There is no such constructor for wx.Cursor containing 8 arguments.

When I try to run the example using the code for the WXMSW platform, the following error occurs.

AttributeError: module ‘wx’ has no attribute ‘BitmapFromBits’

This is the example code from the docs.wxpython.org site

cursor1.py (1.8 KB)

Can anyone provide a working example of creating a custom cursor?

Thanks

The demo contains working code in Cursor.py.

See e.g. PyPi how to get the demo:
https://pypi.org/project/wxPython/

Cursor.py allows someone to see all the stock cursors available to wxPython and also custom cursors loaded from images. .cur or .ani files.

I was looking to get the example code from docs.wxpython.org working correctly.
My apologies for not mentioning this beforehand.

Thanks

The example in the wx.Cursor page in the wxPython documentation originates in this wxWidgets page.

In that C++ version, both down_bits and down_mask are declared as arrays of char.

I have tried several different ways to convert the integer values in the example into strings containing equivalent hex values, but nothing I’ve tried has worked.

I also noticed that there is a BitmapFromBits() function in wx.lib.agw.aui.aui_utilities, but I couldn’t get that to work either.

Personally, if I wanted to create a custom cursor from data values that I could include in a python module, I would start with an image file and generate a PyEmbeddedImage object from it using img2py(). The Cursor example in the wxPython demo includes some code that shows how to create a custom cursor from a PyEmbeddedImage object.

I followed up on Richard’s discovery of a BitmapFromBits method in the wx.lib.agw.aui.aui_utilities module.
I added the BitmapFromBits method to my program.
BitmapFromBits complains that the type of data being passed is invalid when wx.Bitmap is called.
From the documentation for wx.Bitmap, it seems that a string is required.


__init__ (self, bits, width, height, depth=1)
Creates a bitmap from the given array bits.
You should only use this function for monochrome bitmaps (depth 1) in portable programs:
in this case the bits parameter should contain an XBM image.
For other bit depths, the behaviour is platform dependent: under Windows, the data is passed without any changes to the underlying CreateBitmap() API. 
Under other platforms, only monochrome bitmaps may be created using this constructor and wx.Image should be used for creating colour bitmaps from static data.

Parameters:
    bits (string) – Specifies an array of pixel values.
    width (int) – Specifies the width of the bitmap.
    height (int) – Specifies the height of the bitmap.
    depth (int) – Specifies the depth of the bitmap. If this is omitted, then a value of 1 (monochrome bitmap) is used.

Return type:
    None
-----------------------------------------------------------------------------------------------------------------------------

However, when I changed the logic to pass a string, the same error was issued.
It seems that an array was required
I changed the code as follows and the error no longer occurred.

    from array import array
    down_bitmap = self.BitmapFromBits(array(u'B', down_bits), 32, 32, wx.BLACK)

I removed the conditional logic based on platform type
I also had to remove all of the mask logic due to the following error being issued when creating the mask.

    wx._core.wxAssertionError: C++ assertion "bitmap.GetDepth() == 1" failed at ../src/gtk/bitmap.cpp(258) in InitFromMonoBitmap(): Cannot create mask from colour bitmap

This was the final version of the working code.

def BitmapFromBits(self, bits, w, h, colour):
  img = wx.Bitmap(bits, w, h).ConvertToImage()
  return wx.Bitmap(img)

from array import array
down_bitmap = self.BitmapFromBits(array(u'B', down_bits), 32, 32, wx.BLACK)
down_image = down_bitmap.ConvertToImage()
down_image.SetOption(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
down_image.SetOption(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 14)
down_cursor = wx.Cursor(down_image)

Thanks to everyone for their help.

The mistake you’re running into is due to the fact that the constructor for wx.Cursor on your platform takes arguments differently than the one used in the example. In particular, the wx.Cursor constructor you’re using is incompatible with how it deals with the creation of cursors from pixel data in your version of wxPython.