wxWidgets中的高分辨率屏幕(高 DPI)支持
原文为空
介绍
许多现代显示器在相同的屏幕表面上拥有比过去的标准数量多得多的像素,这使得每英寸的DPI(点数,即像素数)值比传统使用的值高得多。这使得文本或一般的几何图形的渲染更加平滑。
作为一个示例,以下是同一段采用11磅Helvetica字体的文本在屏幕上占用相同空间的两种放大视图。第一种是在原始的72像素每英寸(dpi)的Mac显示器上显示的效果,第二种是在高分辨率显示器(苹果公司称之为“视网膜屏”,其两个维度上的像素数量都是前者的两倍,即144dpi,因此在相同屏幕表面上的像素数量是前者的4倍)上显示的效果。使用高分辨率显示器时,文本轮廓的细节要丰富得多。
对于用户而言,DPI通常是用一个缩放系数来表示的,基准DPI值会乘以这个系数。例如,微软Windows系统(MSW)可能会使用125%或150%的缩放比例,这意味着它们分别使用120或144的DPI,因为基准DPI值是96。同样地,Linux系统可能会使用“2倍”缩放,这样得到的DPI值为192。苹果Mac系统稍有不同,即便它们也可能使用“2倍”缩放(就像上面的例子那样),与之对应的有效DPI是144,因为在这个平台上的基准值是72。
高DPI显示器存在的问题
如果以与普通显示器相同的方式对待高DPI显示器,那么现有的应用程序在高DPI显示器上会显得非常小。例如,一个边长为500像素的正方形窗口,在标准的1920×1080(“全高清”)显示器上垂直方向会占据一半的空间,但在3840×2160(“4K超高清”)显示器上就只占据四分之一的空间。为了避免这种情况发生,大多数平台在高DPI显示器上显示窗口时,会自动按照上述定义的缩放系数对窗口进行缩放。在这个例子中,缩放系数是2,所以当自动缩放生效时,该窗口在屏幕上的实际大小会变为1000像素。
自动缩放很方便,但实际上并不能让应用程序利用显示器上额外的像素。从视觉上看,这意味着经过缩放的应用程序会显得模糊,而那些使用了显示器全分辨率的应用程序则更加清晰锐利。因此,需要一个更好的方案来处理高DPI显示器上的像素值:这个方案应允许对某些像素值(例如窗口的总大小)进行缩放,但不对其他一些像素值(例如用于绘图的像素值,为了利用全部可用分辨率,这些值应保持不缩放)进行缩放。
wxWidgets中的像素值
逻辑像素和设备无关像素
某些系统,例如苹果的操作系统,会自动根据DPI缩放系数对所有坐标进行缩放,但并非所有wxWidgets所支持的系统都会这样做 —— 值得注意的是,微软Windows系统(MSW)就不会。这意味着,在使用高DPI显示器时,wxWidgets API中用于表示所有坐标和尺寸的逻辑像素,在不同平台上的含义并不相同。因此,在macOS系统上,无论显示器的分辨率是多少,你始终可以传入 (500, 500) 的尺寸来创建上一段提到的窗口;但在MSW系统上,当使用200%缩放的显示器时,你就得将尺寸增大到 (1000, 1000)。为了向应用程序隐藏这种差异wxWidgets提供了设备无关像素,简称为 “DIP”,它在所有显示器和平台上的大小始终是相同的。
因此,在为你的应用程序准备高DPI支持时,首先要做的就是停止使用原始像素值。实际上,不建议使用任何像素值,更可取的做法是用基于文本度量的值来替代它们,也就是使用wx.Window.GetTextExtent方法获取的值,或者用对话框单位来表示这些值(详见wx.Window.ConvertDialogToPixels方法)。不过,最简单的改动就是直接用设备无关像素(DIP)值来替代像素值:为此,只需使用wx.Window.FromDIP方法在两者之间进行转换即可。
例如,如果你有以下现有的代码:
myFrame.SetClientSize(wx.Size(400, 300))
你可以直接将其替换为:
myFrame.SetClientSize(myFrame.FromDIP(wx.Size(400, 300)))
物理像素
除了上述讨论的(逻辑)像素和设备无关像素(DIP)之外,你可能还需要使用与实际显示像素相对应的物理像素坐标来进行操作。在任何平台上,物理像素都不会被缩放,并且在绘制图形元素时必须使用物理像素,以确保使用尽可能高的分辨率。例如,对wxGLCanvas的所有操作都使用物理像素。
要在逻辑像素和物理像素之间进行转换,你可以使用wx.Window.GetContentScaleFactor方法。这是一个大于或等于1的值,因此需要将逻辑像素值乘以该值,才能得到物理像素值。
例如,在一个创建时大小为100(逻辑)像素的wxGLCanvas中,最右侧的物理像素坐标将是100*GetContentScaleFactor()。
高分辨率图像和艺术品
为了充分利用高DPI设备上更高的细节表现,你可能也希望为应用程序所使用的图像或艺术品提供更高分辨率的版本。请注意,不建议仅提供高分辨率版本,然后让系统在1倍缩放(普通)显示器上将其缩小显示。除了性能方面的考量外,图像质量也可能会受到影响,图像轮廓会变得更加模糊。
你可以使用基于矢量的图形,比如SVG格式的图形,或者你也可以添加不同尺寸/分辨率的同一图像。
特定平台的构建问题
一般来说,所有系统对于未特别标记为 “支持高 DPI” 的应用程序,都会通过模拟低分辨率显示并对其进行放大处理来运行,这会导致图形和字体模糊,但从整体上保留了应用程序的外观。为了获得最佳效果,应用程序需要以依赖于特定平台的方式显式标记为支持高DPI。
微软Windows
待办:此部分仍需更新,以纳入特定于Python的说明。应用程序在高DPI显示器上运行时的表现取决于其清单文件中的值。如果你的应用程序从其资源文件中包含了wx/msw/wx.rc,那么你需要预定义wxUSE_DPI_AWARE_MANIFEST以选择启用高DPI支持:将其定义为1表示最低限度的DPI感知,定义为2则表示支持Windows 10 1703版本或更高版本所具备的完整的每显示器DPI感知功能。
macOS
支持高DPI的应用程序必须在其Info.plist文件中将NSPrincipalClass设置为wxNSApplication(或至少设置为NSApplication)。对于wxPython应用程序,Info.plist文件通常是在为应用程序构建应用程序包时创建的。这是将一组文件制作成macOS能够识别为图形用户界面(GUI)应用程序所需的一部分。如果你使用像PyInstaller这样的工具来构建应用程序包,那么它很可能提供了一种添加或修改Info.plist文件内容的方法,或者你也可以手动编辑该文件。有关更多信息,还可查阅苹果公司的高分辨率指南。