如何阻止显示分辨率影响 pyqtgraph 图中的轴

问题描述

我正在使用 pyqtgraph 绘制一些数据,并注意到当我将绘图从笔记本电脑屏幕移动到第二台显示器时,绘图上的缩放会受到影响:

笔记本电脑显示器:

original laptop

外部监视器:

original ext. monitor

请注意轴被“压缩”,并且绘图在第二台显示器上不再正确缩放。

我在网上发现其他人报告了类似的问题,但找不到任何真正的解决方案。建议的一种解决方案是使显示器的分辨率相同。我不喜欢这个解决方案,因为我不得不牺牲笔记本电脑的分辨率来适应我较低分辨率的外接显示器。

我发现的另一个解决方案是在主循环中添加app.setAttribute(QtCore.Qt.AA_Use96Dpi),在实例化 Qapplication 之前,如下所示,据称让 Qt 忽略操作系统的 DPI 设置:

def main():
 import sys
 app = QtWidgets.QApplication(sys.argv)
 app.setAttribute(QtCore.Qt.AA_Use96Dpi)
 MainWindow =GraphWindow()
 MainWindow.show()
 sys.exit(app.exec_())

这起初似乎有效,因为绘制的数据在轴上正确缩放。然而,它似乎并没有真正起作用——这条线的添加影响了笔记本电脑上轴的缩放,如下所示(现在在 x 轴上跨越 0 到 7000 的轴上绘制了相同的数据,并且—— Y 轴上 2 至 -26dB):

laptop_96DPI setting

,

但是在将绘图移动到第二台显示器上时确实“修复”了这个问题,使其看起来像上面显示的第一个“原始”笔记本电脑绘图。

这尤其令人担忧,因为在 app.setAttribute(QtCore.Qt.AA_Use96Dpi) 指令之后的笔记本电脑输出“看起来”正确,但歪曲了实际数据。当我第一次绘制数据时,我很容易错过这一点。

无论操作系统的 DPI 设置和显示器分辨率如何,准确显示绘图的正确方法是什么?很奇怪,绘制的数据似乎与轴值无关。

这是一个最小的可重现样本:

from PyQt5 import QtWidgets,QtCore
from pyqtgraph import PlotWidget,plot
import pyqtgraph as pg
import sys  # We need sys so that we can pass argv to QApplication
import os
from  numpy.random import seed
from  numpy.random import randint

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self,*args,**kwargs):
        super(MainWindow,self).__init__(*args,**kwargs)

        self.graphWidget = pg.PlotWidget()
        self.setCentralWidget(self.graphWidget)

        x = [1,2,3,4,5,6,7,8,9,10]
        seed(1)
        y = randint(5,35,10)

        # plot data: x,y values
        self.graphWidget.plot(x,y)


def main():
    app = QtWidgets.QApplication(sys.argv)
    app.setAttribute(QtCore.Qt.AA_Use96Dpi)
    main = MainWindow()
    main.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

解决方法

可以在此处找到答案:https://github.com/pyqtgraph/pyqtgraph/issues/756

此问题的快速摘要: 基本上有两种方法可以解决这个问题。

  1. 使您的应用具有 DPI 感知能力(由 Androwei)
import ctypes
import platform

def make_dpi_aware():
    if int(platform.release()) >= 8:
        ctypes.windll.shcore.SetProcessDpiAwareness(True)

# add this code before "app = QtWidgets.QApplication(sys.argv)"
make_dpi_aware()
  1. Qt.HighDpiScaleFactorRoundingPolicy 设置为 PassThrough(by andybarry)
# add this code before "app = QtWidgets.QApplication(sys.argv)"
QtWidgets.QApplication.setAttribute(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)

这两种方法我都试过了,它们都很好用!感谢这些贡献者。希望你也能发现这很有用。