Float values no longer accepted in wxPython-4.1.2a1.dev5259?

Hi,

I installed wxPython-4.1.2a1.dev5259+d3bdb143-cp310-cp310-win_amd64.whl wheel file. I have python 3.10.1 64 bit and Windows 11.

Now I get lots of errors like this:

TypeError: DC.DrawLine(): arguments did not match any overloaded call:
overload 1: argument 1 has unexpected type ‘float’

In wxpython 4.1.1, it accepted float values, but now it asks for integer values only. What is wrong?

You’re using Python 3.10 right? That’s a Python 3.10 change, not a change in wxPython. Methods that accept integers will no longer silently accept and truncate floats.

1 Like

Why on earth would someone introduce a change like that? That’s the most ridiculous thing I’ve ever heard.

Why does DC.DrawLine(), wx.Rect, wx.Pen etc require integer-type arguments in the first place? Why didn’t they made those arguments floats?

Because wx.DCs use integer coordinates. In the wx.DC view of the world there is nothing between pixel (3,1) and (4,1) for example. If you need floating point sub-pixel precision then wx.GraphicsContext is available.

The details for the change in Python are here:Issue 37999: No longer use implicit convertion to int with loss - Python tracker A little searching will probably turn up more discussion about it.

2 Likes

So, even though I pass a floating point argument to wx.DC, it converts it to an integer?

Does wx.DrawLine(3.8 is converted to wx.DrawLine(3 ?

How about wx.Font, it also doesn’t accept float values anymore. What happens to wx.Font(11.7 in python 3.9, is it converted to wx.Font(11 ?

import wx

app = wx.App()

font = wx.Font(11.7, wx.ROMAN, wx.NORMAL, wx.NORMAL)

print("Point size =", font.GetPointSize())

Even with Python 3.8 this gives a DeprecationWarning and, yes the point size is truncated:

richardt@Pavilion ~/.../hci/wxpython/fonts $ python3.8 font_size.py 
font_size.py:5: DeprecationWarning: an integer is required (got type float).  Implicit conversion to integers using __int__ is deprecated, and may be removed in a future version of Python.
  font = wx.Font(11.7, wx.ROMAN, wx.NORMAL, wx.NORMAL)
Point size = 11
1 Like

I don’t understand, I use wx.PaintDC. Does it mean that I use wx.DC? How can I make my app use wx.GraphicsContext?

My code:

self.dc = wx.PaintDC(self)
self.Bind(wx.EVT_PAINT, self.onPaint)

Thus every time the panel is refreshed, everything is redrawn. Do I use wx.DC here? How can I make my app use wx.GraphicsContext?

Out of interest I had a look at drawing text in a wxGraphicsContext. Previously I have used the following to create a GraphicsContext from a DC:

    gcdc = wx.GCDC(dc)
    gc = gcdc.GetGraphicsContext()

But the documentation for GraphicsContext says you can also do:

gc = wx.GraphicsContext.Create(dc)

The GraphicsContext.CreateFont() method takes a float for the sizeInPixels arg, whereas the wx.Font() constructor takes an int for the pointSize arg. So the sizes will be different.

However, since wxPython version 4.1/wxWidgets-3.1.2, wx.Font has a SetFractionalPointSize() method which does take a float as the pointSize arg.

The following code experiments with these ideas:

import wx

class TestPanel(wx.Panel):
    def __init__(self, *args, **kw):
        wx.Panel.__init__(self, *args, **kw)
        self.Bind(wx.EVT_PAINT, self.OnPaint)


    def Draw(self, dc):
        dc.SetBackground(wx.Brush("sky blue"))
        dc.Clear()
        # gcdc = wx.GCDC(dc)
        # gc = gcdc.GetGraphicsContext()
        gc = wx.GraphicsContext.Create(dc)

        gc_font = gc.CreateFont(11.7, facename='')
        gc.SetFont(gc_font)
        gc.DrawText("gc.DrawText()", 20, 20)

        wx_font = wx.Font(11, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL)
        dc.SetFont(wx_font)
        dc.DrawText("dc.DrawText()", 20, 60)

        wx_font.SetFractionalPointSize(11.7)
        dc.SetFont(wx_font)
        dc.DrawText("dc.DrawText()", 20, 80)

        wx_font.SetFractionalPointSize(12.0)
        dc.SetFont(wx_font)
        dc.DrawText("dc.DrawText()", 20, 100)


    def OnPaint(self, evt):
        dc = wx.PaintDC(self)
        self.Draw(dc)


if __name__ == '__main__':
    app = wx.App()
    frame = wx.Frame(None, title="Graphics Context Test", size=(300, 200))
    pnl = TestPanel(frame)
    frame.Show()
    app.MainLoop()


Tested on Python 3.8.10 + wxPython 4.1.1 gtk3 (phoenix) wxWidgets 3.1.5 + Linux Mint 20.2

Thanks but, when you do

wx.GraphicsContext doesn’t have methods like SetTextForeground, which PaintDC have. How to solve this?

The only way I have found to do this is to create a wx.Font, set its fractional point size and then pass it with a colour to the GraphicsContext’s overloaded SetFont() method:

        wx_font = wx.Font(11, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL)
        wx_font.SetFractionalPointSize(11.7)
        gc.SetFont(wx_font, wx.RED)
        gc.DrawText("gc.DrawText()", 20, 80)

However, that may defeat the point of using a GraphicsContext in the first place.

1 Like