Re: wx.Python 2.9: dc.SetMapMode(wx.MM_TWIPS) and wx.Fonts

132 views
Skip to first unread message

Vadim Zeitlin

unread,
Nov 9, 2012, 7:11:34 AM11/9/12
to wx-u...@googlegroups.com
On Fri, 9 Nov 2012 00:04:36 -0800 (PST) Gregory Papadopoulos wrote:

GP> I have a problem with 2.9 (just began using it).

Under which platform did you test this?

GP> I want to get
GP> dc.SetMapMode(wx.MM_TWIPS)
GP> ...
GP> dc.SetUserScale(self.zoom, self.zoom)
GP> ...
GP> # Get the font
GP> font = dc.GetFont()
GP> font.SetPointSize(int(self.zoom*dc.DeviceToLogicalYRel(12))) # Works in 2.8

I think it should be just

font.SetPointSize(12)

I didn't realize that this changed since 2.8 but the current behaviour
seems to be logical to me as the font size adjusts to the scaling/mapping
mode just as everything else does.

FWIW it could be argued that the size specified in points shouldn't depend
on scaling as a point is a physical unit, just as a centimeter, but I think
this would be quite surprising.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Gregory Papadopoulos

unread,
Nov 9, 2012, 9:00:35 AM11/9/12
to wx-u...@googlegroups.com
I've been testing this on Win XP and Win 7 64bit (python 2.7 32bit, wxPython 2.8 unicode )

VZ>  I think it should be just        
VZ>  font.SetPointSize(12)
 
Indeed it should be like that. Since I am working in wx.MM_TWIPS the actual font is about 182points big.
The function above (self.zoom*dc.DeviceToLogicalYRel(12)) just sets the font to appear like it would if pointsize 12 was used in wx.MM_POINTS for the appropriate zoom.

But that is not the point.
Even if i just set it to font.SetPointSize(12), when SetUserScale is called, the font doesn't "zoom" (only in wx 2.9), while everything else does.
And this is my problem. It is opposite to what you are pointing out yourself.

Vadim Zeitlin

unread,
Nov 9, 2012, 9:11:38 AM11/9/12
to wx-u...@googlegroups.com
On Fri, 9 Nov 2012 06:00:35 -0800 (PST) Gregory Papadopoulos wrote:

GP> I've been testing this on Win XP and Win 7 64bit (python 2.7 32bit,
GP> wxPython 2.8 unicode )

And which version of 2.9? Please retest if it wasn't the latest one
because I don't see what you're seeing here.

GP> VZ> I think it should be just font.SetPointSize(12)
GP>
GP> Indeed it should be like that. Since I am working in wx.MM_TWIPS the actual
GP> font is about 182points big.

Err, its physical size should be much smaller than 12 points, not larger,
in TWIPS mapping mode.

GP> Even if i just set it to font.SetPointSize(12), when SetUserScale is
GP> called, the font doesn't "zoom" (only in wx 2.9), while everything else
GP> does.

It does for me in the drawing sample included with wxWidgets. Both
changing the mapping mode and the scale (see the appropriate menus in this
sample) change the font size.

Gregory Papadopoulos

unread,
Nov 9, 2012, 11:56:28 AM11/9/12
to wx-u...@googlegroups.com


I'm attaching screenshot of the result in both systems and a stripped down code that reproduces the problem.
Its the same script.
The left one is on WinXP, 64bit Python 2.7.3 32bit with wx.Python 2.8.12.1 32 bit unicode for Py2.7
The right one is on Win7 64bit Python 2.7.3 32bit with wx.Python 2.9.4.0 32bit for Py2.7


wx2_9_hview.py

Vadim Zeitlin

unread,
Nov 9, 2012, 11:58:43 AM11/9/12
to wx-u...@googlegroups.com
On Fri, 9 Nov 2012 08:56:28 -0800 (PST) Gregory Papadopoulos wrote:

GP> I'm attaching screenshot of the result in both systems and a stripped down
GP> code that reproduces the problem.

It would be really great if you could strip it down further because it's
quite huge now.

TIA,

Gregory Papadopoulos

unread,
Nov 9, 2012, 12:10:36 PM11/9/12
to wx-u...@googlegroups.com
I just left some helper functions like a zoomin/out with numpad+/numpad-.
Only thing to check is OnPaint and DrawMain
wx2_9_hview_.py

Vadim Zeitlin

unread,
Nov 9, 2012, 3:49:42 PM11/9/12
to wx-u...@googlegroups.com
On Fri, 9 Nov 2012 09:10:36 -0800 (PST) Gregory Papadopoulos wrote:

GP> I just left some helper functions like a zoomin/out with numpad+/numpad-.
GP> Only thing to check is OnPaint and DrawMain

I'm sorry, I can't reproduce the problem. Here is the patch I used:

diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
index a78e462..1ac2156 100644
--- a/samples/minimal/minimal.cpp
+++ b/samples/minimal/minimal.cpp
@@ -68,6 +68,14 @@ class MyFrame : public wxFrame
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);

+ void OnPaint(wxPaintEvent&)
+ {
+ wxPaintDC dc(this);
+ dc.SetMapMode(wxMM_TWIPS);
+ dc.SetFont(wxFont(182, wxFONTFAMILY_DEFAULT, wxFONTFLAG_DEFAULT));
+ dc.DrawText("Whatever", 100, 100);
+ }
+
private:
// any class wishing to process wxWidgets events must use this macro
DECLARE_EVENT_TABLE()
@@ -99,6 +107,7 @@ enum
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
+ EVT_PAINT(MyFrame::OnPaint)
END_EVENT_TABLE()

// Create a new application object: this macro will allow wxWidgets to create


The string appears in a correct, certainly not tiny and illegible, font on
the screen.

Please try doing the same thing as above (i.e. just define a paint handler
doing what I did) in Python and post here if you still see the problem.

Regards,

Gregory Papadopoulos

unread,
Nov 10, 2012, 11:36:42 AM11/10/12
to wx-u...@googlegroups.com
I did what you proposed and it works just fine. Really thanks for that.
Just in case anybody is interested, I didn't leave it to that, and so tried to locate where the problem was in my code.
What I was doing (and worked in wx 2.8) was getting the dc font and the manipulating its properties, changing the face all the while. Something like:
font = dc.GetFont()
font.SetFaceName(facename)
font.SetPointSize(pointsize)
font.SetStyle(wx.FONTSTYLE_NORMAL)
font.SetWeight(wx.FONTWEIGHT_NORMAL)
dc.SetFont(font)
I know it not the most compact way of programming, instead I thought it'd be better not to create a new wx.Font object.

Now in wx 2.9 this code doesn't work properly unless you've already set a font, like:
dc.SetFont(wx.Font(12, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
So adding this line before font = dc.GetFont() fixes my problem.
Now I am asking myself if I should expect that.

Vadim Zeitlin

unread,
Nov 11, 2012, 7:43:50 AM11/11/12
to wx-u...@googlegroups.com
On Sat, 10 Nov 2012 08:36:42 -0800 (PST) Gregory Papadopoulos wrote:

GP> What I was doing (and worked in wx 2.8) was getting the dc font and the
GP> manipulating its properties, changing the face all the while. Something
GP> like:
GP> font = dc.GetFont()
GP> font.SetFaceName(facename)
GP> font.SetPointSize(pointsize)
GP> font.SetStyle(wx.FONTSTYLE_NORMAL)
GP> font.SetWeight(wx.FONTWEIGHT_NORMAL)
GP> dc.SetFont(font)
GP> I know it not the most compact way of programming, instead I thought it'd
GP> be better not to create a new wx.Font object.

wxFont objects are pretty lightweight, it's the fonts themselves (i.e. the
graphical objects actually used for drawing) that are not. And a new such
underlying object is created whenever you call any wxFont::SetXXX(), so the
above doesn't really save you anything.

GP> Now in wx 2.9 this code doesn't work properly unless you've already set a
GP> font, like:
GP> dc.SetFont(wx.Font(12, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL,
GP> wx.FONTWEIGHT_NORMAL))
GP> So adding this line before font = dc.GetFont() fixes my problem.
GP> Now I am asking myself if I should expect that.

No, you shouldn't. And the trouble is that, just as before, I can't
reproduce the problem you have, e.g. this code:

void OnPaint(wxPaintEvent&)
{
wxPaintDC dc(this);
dc.SetMapMode(wxMM_TWIPS);
wxFont font(dc.GetFont());
font.SetPointSize(182);
dc.SetFont(font);
dc.DrawText("Whatever", 100, 100);
}

works just fine for me too.

Gregory Papadopoulos

unread,
Nov 12, 2012, 5:03:13 AM11/12/12
to wx-u...@googlegroups.com
This time I can verify that it doesn't work otherwise. This is the paint routine that doesn't work

def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc.SetMapMode(wx.MM_TWIPS)
        font = dc.GetFont()
        font.SetPointSize(182)
        dc.SetFont(font)
        dc.DrawText('How about now', 0, 0)

while this works:

def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc.SetMapMode(wx.MM_TWIPS)
        dc.SetFont(wx.Font(182, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
        font = dc.GetFont()
        font.SetPointSize(182)
        dc.SetFont(font)
        dc.DrawText('How about now', 0, 0)

The first piece does exactly what you are proposing on your C++ code. Well, besides the text rendered and its position.
The second just works, even on the original code by adding that line (or any equivalent I guess).

Would you like me to take a deeper look into it? Any thoughts/proposals on what we should do?

Vadim Zeitlin

unread,
Nov 12, 2012, 6:26:55 AM11/12/12
to wx-u...@googlegroups.com
On Mon, 12 Nov 2012 02:03:13 -0800 (PST) Gregory Papadopoulos wrote:

GP> This time I can verify that it doesn't work otherwise. This is the paint
GP> routine that doesn't work
GP>
GP> def OnPaint(self, event):
GP> dc = wx.PaintDC(self)
GP> dc.SetMapMode(wx.MM_TWIPS)
GP> font = dc.GetFont()
GP> font.SetPointSize(182)
GP> dc.SetFont(font)
GP> dc.DrawText('How about now', 0, 0)
GP>
GP> while this works:
GP>
GP> def OnPaint(self, event):
GP> dc = wx.PaintDC(self)
GP> dc.SetMapMode(wx.MM_TWIPS)
GP> dc.SetFont(wx.Font(182, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL,
GP> wx.FONTWEIGHT_NORMAL))
GP> font = dc.GetFont()
GP> font.SetPointSize(182)
GP> dc.SetFont(font)
GP> dc.DrawText('How about now', 0, 0)
GP>
GP> The first piece does exactly what you are proposing on your C++ code. Well,
GP> besides the text rendered and its position.
GP> The second just works, even on the original code by adding that line (or
GP> any equivalent I guess).

Strange, I don't see why would the behaviour be different in Python and
C++.

GP> Would you like me to take a deeper look into it? Any thoughts/proposals on
GP> what we should do?

First, could you please check if the problem persists if you draw directly
on wxFrame, like my code did, or if it only happens when using
wxScrolledWindow?

Second, please try to test with the latest svn if possible or retest with
2.9.5 when it's out. While I don't remember any relevant changes in the
code, perhaps something did change recently.

Thanks,

Gregory Papadopoulos

unread,
Nov 12, 2012, 6:57:16 AM11/12/12
to wx-u...@googlegroups.com
 Strange, I don't see why would the behaviour be different in Python and
C++.

Same here. I don't get it. I was thinking of moving the code to C++, but for the time being I am forced to use Python. (+ it is faster to develop :)

 First, could you please check if the problem persists if you draw directly
on wxFrame, like my code did, or if it only happens when using
wxScrolledWindow? 

Same result for wx.Panel. Leaning towards believing it's related to the font system
 
 Second, please try to test with the latest svn if possible or retest with
2.9.5 when it's out. While I don't remember any relevant changes in the
code, perhaps something did change recently.

I'll get the svn if its not a big deal to setup in a system. Can't test it right away.
I should be thanking you.
Greg

Robin Dunn

unread,
Nov 12, 2012, 1:06:15 PM11/12/12
to wx-u...@googlegroups.com
One difference is that the C++ code made a copy of the dc's font:

wxFont font(dc.GetFont());

but the Python code was using and modifying the same font already set in
the DC, if any:

font = dc.GetFont()

Since GetFont is returning a reference then it will be the same font
object that is already set in the DC. I seem to recall that there was
some change in the last several months related to the default font in
DCs, perhaps that is part of the cause of the different results?

--
Robin Dunn
Software Craftsman
http://wxPython.org

Gregory Papadopoulos

unread,
Nov 12, 2012, 1:21:10 PM11/12/12
to wx-u...@googlegroups.com
Indeed that seems to be the main difference.
But dc.GetFont() returns a wx.Font object, which is a copy of the one already set. After that if you make changes you have to set the font with dc.SetFont( the_wx.FontObject )
I think it will be better to have a look into wx.Python code to see what is done there


Reply all
Reply to author
Forward
0 new messages