Skip to content

Invalid pixel ratio update when changing screen resolution #19656

Closed
@rayosborn

Description

@rayosborn

Bug report

Bug summary

When switching from an external monitor, with a dpi ratio of 1.0, to my MacBook Pro laptop, with a dpi ratio of 2.0, existing PyQt windows containing Matplotlib plots look fine after waking from sleep but switch to a quarter size as soon as I select the window, i.e., the fix in the PR #19123 doesn't seem to work in this scenario.

Code for reproduction

I am using the NeXpy package, which embeds Matplotlib canvases in separate PyQt5 windows. Each window is added to a dictionary, called plotviews, which is available to an embedded Python shell. If I initially plot on my external monitor, I get the following plot:
external-monitor
In the shell, I see the following ratios.

In [1]: for pv in plotviews:
            print(plotviews[pv].canvas._dpi_ratio, plotviews[pv].canvas._dpi_ratio_prev)
1.0 1.0
1.0 1.0
1.0 1.0

Actual outcome
When I switch to my laptop, the plots look fine initially, but as soon as I select any window, the plot shrinks to quarter size:
laptop-screen

In [2]: for pv in plotviews:
            print(plotviews[pv].canvas._dpi_ratio, plotviews[pv].canvas._dpi_ratio_prev)
2.0 1.0
2.0 1.0
2.0 1.0

After the plots have shrunk, the _dpi_ratio_prev has still not been updated.

In [3]: for pv in plotviews:
            print(plotviews[pv].canvas._dpi_ratio, plotviews[pv].canvas._dpi_ratio_prev)
2.0 1.0
2.0 1.0
2.0 1.0

Expected outcome
Obviously, the plots should not change size. Selecting the window does not appear to trigger the canvas showEvent function. I'm not sure what does. If I force an update, the plot does expand to the correct size. Note that _dpi_ratio_prev has been updated after the explicit call to _update_screen but only for the third figure. The others are still shrunk.

In [4]: screen=plotviews['Figure 3'].canvas.window().windowHandle()
In [5]: plotviews['Figure 3'].canvas._update_screen(screen.screen())
In [6]: for pv in plotviews:
            print(plotviews[pv].canvas._dpi_ratio, plotviews[pv].canvas._dpi_ratio_prev)
2.0 1.0
2.0 1.0
2.0 2.0

I wonder if the screenChanged signal should be connected to _update_screen at an earlier stage in initializing the window without depending on a call to showEvent.

Matplotlib version

  • Operating system: Mac OS X 10.15.7
  • Matplotlib version: 3.4.0rc1
  • Matplotlib backend: Qt5agg
  • Python version: 3.8.6
  • PyQt5 version: 5.15.2

I used pip to update to the latest release candidate within a conda environment.

Edited to correct reference to the screen.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions