Skip to content

WxAgg backend draws the wrong size when wxpython app is high DPI aware on Windows #18940

Closed
@jbhopkins

Description

@jbhopkins

Bug report

In wxpython 4.1.0 initial support was added for high DPI awareness on Windows. Using matplotlib with the wxAgg backend and wxpython 4.1.0 on Windows results in everything being drawn at the wrong size. This is shown below, where the same plot is made without (left) and with (right) high DPI awareness turned on. For reference, I'm doing this on a 5120x2880 display with scale factor set to 200%.

Left, without high DPI awareness, right with high DPI awareness:
low_and_high_dpi

Code for reproduction

import ctypes

import wx
import matplotlib as mpl
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg

class PlotFrame(wx.Frame):
    def __init__(self, parent, title, *args, **kwargs):
        wx.Frame.__init__(self, parent, title=title, *args, **kwargs)

        self.fig = mpl.figure.Figure((5,4))
        self.subplot1 = self.fig.add_subplot(111)
        self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.fig)

        self.toolbar = NavigationToolbar2WxAgg(self.canvas)
        self.toolbar.Realize()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        sizer.Add(self.toolbar, 0, wx.GROW)

        self.subplot1.plot([0, 1, 2, 3, 4], [0, 2, 4, 9, 16], '-o')

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()
        self.CenterOnScreen()
        self.Show(True)

if __name__ == '__main__':
    # Windows high DPI support
    try:
        ctypes.windll.shcore.SetProcessDpiAwareness(True)
    except:
        pass

    app = wx.App(False)
    frame = PlotFrame(None, 'My Plot Frame')
    app.MainLoop()

Alternatively, using pyplot the issue is also reproduced:

import ctypes

import matplotlib as mpl
import matplotlib.pyplot as plt

# Windows high DPI support
try:
    ctypes.windll.shcore.SetProcessDpiAwareness(True)
except:
    pass

mpl.use('wxAgg')

plt.plot(range(10), range(10)[::-1])
plt.show()

Actual and expected outcomes
Actual outcome is a window that is half size, with all fonts, line thicknesses, icons, etc at half size (presumably because it's not accounting for the 200% scale factor). The expected outcome is something identical to the plot with high DPI awareness turned off, except sharp (i.e. natively rendering fonts, lines, etc at 2x size, instead of rendering at 1x and then Windows doing the scaling).

This is shown in the image above, reproduced here:
low_and_high_dpi

Matplotlib version

  • Operating system: Windows 10
  • Matplotlib version: Latest from git, displays as 3.3.2+1628.gfa547835c
  • Matplotlib backend (print(matplotlib.get_backend())): WxAgg
  • Python version: 3.8.2
  • Other libraries: Wxpython 4.1.0
  • Additional info: Tested on a 5120x2880 display with scale factor set to 200%.

Python installed through conda, matplotlib installed from source, wxpython 4.1.0 installed via pip (4.1.0 not available on conda yet).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions