Solved: Unexplainable Font.SetPixelSize error

I get python-BaseException when trying to change the font size.
I printed out the new size before calling SetPixelSize() and the font height is always between 10 and 100 and the width is always 0…

from datetime import datetime

import wx

def_dtf = “%a %d-%b %H:%M:%S”
def Now()->str:
return datetime.now().strftime(def_dtf)
class DClock(wx.Panel):
def init(self, P, **args):
super().init§
self.tfdt:wx.StaticText = wx.StaticText(self, -1, Now())
Z = wx.BoxSizer()
Z.Add(self.tfdt, 1, wx.EXPAND)
self.SetSizerAndFit(Z)
self.Bind(wx.EVT_TIMER, self.tick)
self.Bind(wx.EVT_MOUSEWHEEL, self.wheel)
self.timer = wx.Timer(self)
self.timer.Start(1000)

def resize(self):
	dc=wx.WindowDC(self)
	t=self.tfdt.GetLabel()
	w,h=dc.GetTextExtent(t)
	self.SetSize((w*1.1,h*1.1))
	self.Parent.SetClientSize(self.Size)
	self.Refresh()

def wheel(self, e:wx.MouseEvent):
	r = e.GetWheelRotation()
	if r < 0:self.pan(-r)
	else: self.zoom(r)

def zoom(self, r):  # ignore r for now
	f: wx.Font = self.tfdt.GetFont()
	w, h = f.GetPixelSize()
	print(f"zoom: old font size ={(w,h)}")
	w,h= 0,min(100,h*10/9)
	print(f"zoom: new font size={(w, h)}")
	f.SetPixelSize((w,h))
	self.SetFont(f)
	self.resize()

def pan(self, r):  # ignore r for now
	f: wx.Font = self.tfdt.GetFont()
	w, h = f.GetPixelSize()
	print(f"pan: old font size ={(w, h)}")
	w, h= 0,max(10, h * 9 / 10)
	print(f"pan: new font size={(w, h)}")
	f.SetPixelSize((w,h))
	self.SetFont(f)
	self.resize()

def tick(self, e):
	self.tfdt.SetLabel(Now())
	self.tfdt.Refresh()

class App(wx.App):
def init(self):
super().init()
F = wx.Frame(None, -1, “steve clock”)
C = DClock(F)
Z = wx.BoxSizer()
Z.Add(C, 1, wx.EXPAND)
F.SetSizerAndFit(Z)
F.Show()

if name == “main”:
App().MainLoop()

output

zoom: old font size =(16, 36)
zoom: new font size=(0, 40.0) ### No negative values!!!
Traceback (most recent call last):
File “/home/steve/PycharmProjects/soloa_light/clock/dclock.py”, line 34, in wheel
else: self.zoom®
^^^^^^^^^^^^
File “/home/steve/PycharmProjects/soloa_light/clock/dclock.py”, line 42, in zoom
f.SetPixelSize((w,h))
wx._core.wxAssertionError: C++ assertion "“pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0"” failed at ./src/common/fontcmn.cpp(282) in SetPixelSize(): Negative values for the pixel size or zero pixel height are not allowed

pan

pan: old font size =(16, 36)
pan: new font size=(0, 32.4)
Traceback (most recent call last):
File “/home/steve/PycharmProjects/soloa_light/clock/dclock.py”, line 33, in wheel
if r < 0:self.pan(-r)
^^^^^^^^^^^^
File “/home/steve/PycharmProjects/soloa_light/clock/dclock.py”, line 52, in pan
f.SetPixelSize((w,h))
wx._core.wxAssertionError: C++ assertion "“pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0"” failed at ./src/common/fontcmn.cpp(282) in SetPixelSize(): Negative values for the pixel size or zero pixel height are not allowed

width is zero, which is allowed, and height is positive.
Am I doing something wrong?

Out of curiosity, does anything change if you use something like:

SetPixelSize(wx.Size(0, new_height))

Or:

SetPixelSize((0, int(round(new_height))))

?

I confused wx.Font with another toolkit that uses floats for fonts.
No need to use wx.Size specifically, SetPixelSize((int,int)) works.
Thanks.

The error message didn’t mention that floats were the problem.
Would have been nice.

The error message is indeed extremely misleading.

I’m also unclear how that assert could possibly trigger: even if width and height are floats, so what? As long as their integer parts are greater than zero, they will get truncated to the nearest integer and the assert should not trigger.

Unless of course recent versions of Python are doing funny stuff if you pass floats to C/C++ extensions that are expecting integers. Another gem like the print vs. print() change.

Andrea.

@Andrea_Gavana that is exactly what happened in CPython 3.10: it now throws an exception when a float is passed to a C extension that is expecting an int. The error shown above is not the one from CPython though. It appears to be coming from wxWidgets.