如何使用 python PyQt5 确定我的应用程序 (window) 的活动屏幕(监视器)?
How to determine an active screen (monitor) of my Application (window) using python PyQt5?
我正在开发一个使用许多小部件(QGroupBox、QVBoxLayout、QHBoxLayout)的应用程序。最初它是在普通高清显示器上开发的。但是,最近我们中的许多人升级到了 4K 分辨率显示器。现在一些按钮和滑块被压缩得非常小以至于无法使用。
现在我尝试进行一些更改,以便该应用程序可以与高清和 4K 显示器一起使用。
我开始阅读下面的link:
https://leomoon.com/journal/python/high-dpi-scaling-in-pyqt5/enter link description here
我想每当我的 window 在特定监视器中打开时,我都可以调用以下代码:
if pixel_x > 1920 and pixel_y > 1080:
Qapp.setAttribute(Qt.AA_EnableHighDpiScaling, True)
Qapp.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
else:
Qapp.setAttribute(Qt.AA_EnableHighDpiScaling, False)
Qapp.setAttribute(Qt.AA_UseHighDpiPixmaps, False)
然后我尝试使用以下代码从相关的 post here.
中获取显示器分辨率(pixel_x 和 pixel_y)
import sys, ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
screen_width = 0 #78
screen_height = 1 #79
[pixel_x , pixel_y ] = [user32.GetSystemMetrics(screen_width), user32.GetSystemMetrics(screen_height)]
screen_width = 0, screen_height = 1
给出了我的主显示器的分辨率(在我们的案例中主要是高清笔记本电脑)。 screen_width = 78, screen_height = 79
给了我虚拟机的组合分辨率。但我不明白如何根据我的应用程序打开的位置动态获取这些值。
我的应用程序 window 以这样一种方式开发,它将在上次关闭的同一监视器中打开。现在的问题是我想在调用 GUI 时获得活动监视器分辨率并适应该分辨率。如果有人能帮助我,我会很高兴。
我想知道每次将 window 从高清显示器拖到 4K 显示器时是否可以调用屏幕分辨率计算,反之亦然。
编辑:我在这个 post here 中发现了类似的东西,但我无法从中得到太多。
Edit2:基于@Joe 解决方案,主屏幕检测,为什么我的主屏幕始终是我的笔记本电脑分辨率,即使我 运行 在 4K 屏幕上运行应用程序?
我刚刚尝试使用以下代码获取所有屏幕的 dpi:
def screen_selection():
app = QApplication(sys.argv)
valid_screens = []
for index, screen_no in enumerate(app.screens()):
screen = app.screens()[index]
dpi = screen.physicalDotsPerInch()
valid_screens.append(dpi)
return valid_screens
我across的一个解决方案是使用临时QApplication()
:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
# fire up a temporary QApplication
def get_resolution():
app = QtWidgets.QApplication(sys.argv)
print(app.primaryScreen())
d = app.desktop()
print(d.screenGeometry())
print(d.availableGeometry())
print(d.screenCount())
g = d.screenGeometry()
return (g.width(), g.height())
x, y = get_resolution()
if x > 1920 and y > 1080:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
else:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, False)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, False)
# Now your code ...
此函数将检测所有附加的屏幕:
# fire up a temporary QApplication
def get_resolution_multiple_screens():
app = QtGui.QGuiApplication(sys.argv)
#QtWidgets.QtGui
all_screens = app.screens()
for s in all_screens:
print()
print(s.name())
print(s.availableGeometry())
print(s.availableGeometry().width())
print(s.availableGeometry().height())
print(s.size())
print(s.size().width())
print(s.size().height())
print()
print('primary:', app.primaryScreen())
print('primary:', app.primaryScreen().availableGeometry().width())
print('primary:', app.primaryScreen().availableGeometry().height())
# now choose one
您可以使用提示 and 获取应用程序所在的屏幕 运行。
不过我觉得primaryScreen
也应该return这个:
primaryScreen : QScreen* const
This property holds the primary (or default) screen of the
application.
This will be the screen where QWindows are initially shown, unless
otherwise specified.
(https://doc.qt.io/qt-5/qguiapplication.html#primaryScreen-prop)
嗯,创建主窗口后,您可以直接调用QMainWindow.screen()。 returns 主窗口所在的当前屏幕。这至少允许您在应用程序开始时检查屏幕分辨率。
现在还没有 screenChangeEvent 这样的东西。但是我相信您可以通过子类化 MainWindow 并重载 QMainWindow.moveEvent
来创建一个
例如:
class MainWindow(QtWidgets.QMainWindow):
screenChanged = QtCore.pyqtSignal(QtGui.QScreen, QtGui.QScreen)
def moveEvent(self, event):
oldScreen = QtWidgets.QApplication.screenAt(event.oldPos())
newScreen = QtWidgets.QApplication.screenAt(event.pos())
if not oldScreen == newScreen:
self.screenChanged.emit(oldScreen, newScreen)
return super().moveEvent(event)
这将检查屏幕是否已更改。如果有,它会发出信号。现在你只需要将这个信号连接到一个设置你的 dpi 属性的函数。该事件使您可以访问旧屏幕和新屏幕。
警告:
其中一个屏幕可以是 None
在您的应用程序开始时,因为当您第一次启动您的应用程序时没有 oldScreen
。所以请检查这个。
虽然我无法获得直接的解决方案,但我能够开发一种方法来获得我想要的东西。在几个链接和以前的 post 的帮助下,我能够实现。 我想到了跟踪鼠标事件。
我开发了一种方法来跟踪所有监视器和各自的凝视位置。如果我的变量命名不合适我很乐意接受更改
def get_screen_resolution():
app = QApplication(sys.argv)
screen_count = QGuiApplication.screens()
resolutions_in_x = []
for index, screen_names in enumerate(screen_count):
resolution = screen_count[index].size()
height = resolution.height()
width = resolution.width()
resolutions_in_x.append(width)
low_resolution_monitors = {}
high_resolution_monitors = {}
for i, wid_res in enumerate(resolutions_in_x):
if wid_res > 1920:
high_resolution_monitors.update({i: wid_res})
else:
low_resolution_monitors.update({'L': wid_res})
temp_value = 0
high_res_monitors_x_position = []
low_res_monitors_x_position = []
for i in range(len(screen_count)):
temp_value = temp_value+resolutions_in_x[i]
if resolutions_in_x[i] in high_resolution_monitors.values():
high_res_monitors_x_position.append(temp_value-resolutions_in_x[i])
else:
low_res_monitors_x_position.append(temp_value-resolutions_in_x[i])
total_width_res = []
pixel_value = 0
first_pixel = 0
for i, wid_value in enumerate(resolutions_in_x):
pixel_value = pixel_value + wid_value
total_width_res.append(tuple((first_pixel, pixel_value-1)))
first_pixel = pixel_value
return high_res_monitors_x_position, low_res_monitors_x_position, total_width_res
def moveEvent(self, event):
screen_pos = self.pos()
screen_dimensions = [screen_pos.x(),screen_pos.y()]
super(MainWindow, self).moveEvent(event)
Window_starting_pt = screen_pos.x()
for i, value in enumerate(self.total_width_res):
if value[0]<=Window_starting_pt+30 <=value[1] or value[0]<=Window_starting_pt-30 <=value[1]: #taking 30pixels as tolerance since widgets are staring at some negative pixel values
if value[0] in self.high_res_monitors_x_position:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
else:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, False)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, False)
使用 aboe 的两个函数可以跟踪我的应用程序 (window) 位置并且还可以跟踪它何时被拖到 windows
我正在开发一个使用许多小部件(QGroupBox、QVBoxLayout、QHBoxLayout)的应用程序。最初它是在普通高清显示器上开发的。但是,最近我们中的许多人升级到了 4K 分辨率显示器。现在一些按钮和滑块被压缩得非常小以至于无法使用。
现在我尝试进行一些更改,以便该应用程序可以与高清和 4K 显示器一起使用。
我开始阅读下面的link:
https://leomoon.com/journal/python/high-dpi-scaling-in-pyqt5/enter link description here
我想每当我的 window 在特定监视器中打开时,我都可以调用以下代码:
if pixel_x > 1920 and pixel_y > 1080:
Qapp.setAttribute(Qt.AA_EnableHighDpiScaling, True)
Qapp.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
else:
Qapp.setAttribute(Qt.AA_EnableHighDpiScaling, False)
Qapp.setAttribute(Qt.AA_UseHighDpiPixmaps, False)
然后我尝试使用以下代码从相关的 post here.
中获取显示器分辨率(pixel_x 和 pixel_y)import sys, ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
screen_width = 0 #78
screen_height = 1 #79
[pixel_x , pixel_y ] = [user32.GetSystemMetrics(screen_width), user32.GetSystemMetrics(screen_height)]
screen_width = 0, screen_height = 1
给出了我的主显示器的分辨率(在我们的案例中主要是高清笔记本电脑)。 screen_width = 78, screen_height = 79
给了我虚拟机的组合分辨率。但我不明白如何根据我的应用程序打开的位置动态获取这些值。
我的应用程序 window 以这样一种方式开发,它将在上次关闭的同一监视器中打开。现在的问题是我想在调用 GUI 时获得活动监视器分辨率并适应该分辨率。如果有人能帮助我,我会很高兴。
我想知道每次将 window 从高清显示器拖到 4K 显示器时是否可以调用屏幕分辨率计算,反之亦然。
编辑:我在这个 post here 中发现了类似的东西,但我无法从中得到太多。
Edit2:基于@Joe 解决方案,主屏幕检测,为什么我的主屏幕始终是我的笔记本电脑分辨率,即使我 运行 在 4K 屏幕上运行应用程序?
我刚刚尝试使用以下代码获取所有屏幕的 dpi:
def screen_selection():
app = QApplication(sys.argv)
valid_screens = []
for index, screen_no in enumerate(app.screens()):
screen = app.screens()[index]
dpi = screen.physicalDotsPerInch()
valid_screens.append(dpi)
return valid_screens
我across的一个解决方案是使用临时QApplication()
:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
# fire up a temporary QApplication
def get_resolution():
app = QtWidgets.QApplication(sys.argv)
print(app.primaryScreen())
d = app.desktop()
print(d.screenGeometry())
print(d.availableGeometry())
print(d.screenCount())
g = d.screenGeometry()
return (g.width(), g.height())
x, y = get_resolution()
if x > 1920 and y > 1080:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
else:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, False)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, False)
# Now your code ...
此函数将检测所有附加的屏幕:
# fire up a temporary QApplication
def get_resolution_multiple_screens():
app = QtGui.QGuiApplication(sys.argv)
#QtWidgets.QtGui
all_screens = app.screens()
for s in all_screens:
print()
print(s.name())
print(s.availableGeometry())
print(s.availableGeometry().width())
print(s.availableGeometry().height())
print(s.size())
print(s.size().width())
print(s.size().height())
print()
print('primary:', app.primaryScreen())
print('primary:', app.primaryScreen().availableGeometry().width())
print('primary:', app.primaryScreen().availableGeometry().height())
# now choose one
您可以使用提示
不过我觉得primaryScreen
也应该return这个:
primaryScreen : QScreen* const
This property holds the primary (or default) screen of the application.
This will be the screen where QWindows are initially shown, unless otherwise specified.
(https://doc.qt.io/qt-5/qguiapplication.html#primaryScreen-prop)
嗯,创建主窗口后,您可以直接调用QMainWindow.screen()。 returns 主窗口所在的当前屏幕。这至少允许您在应用程序开始时检查屏幕分辨率。
现在还没有 screenChangeEvent 这样的东西。但是我相信您可以通过子类化 MainWindow 并重载 QMainWindow.moveEvent
例如:
class MainWindow(QtWidgets.QMainWindow):
screenChanged = QtCore.pyqtSignal(QtGui.QScreen, QtGui.QScreen)
def moveEvent(self, event):
oldScreen = QtWidgets.QApplication.screenAt(event.oldPos())
newScreen = QtWidgets.QApplication.screenAt(event.pos())
if not oldScreen == newScreen:
self.screenChanged.emit(oldScreen, newScreen)
return super().moveEvent(event)
这将检查屏幕是否已更改。如果有,它会发出信号。现在你只需要将这个信号连接到一个设置你的 dpi 属性的函数。该事件使您可以访问旧屏幕和新屏幕。
警告:
其中一个屏幕可以是 None
在您的应用程序开始时,因为当您第一次启动您的应用程序时没有 oldScreen
。所以请检查这个。
虽然我无法获得直接的解决方案,但我能够开发一种方法来获得我想要的东西。在几个链接和以前的 post 的帮助下,我能够实现。
我开发了一种方法来跟踪所有监视器和各自的凝视位置。如果我的变量命名不合适我很乐意接受更改
def get_screen_resolution():
app = QApplication(sys.argv)
screen_count = QGuiApplication.screens()
resolutions_in_x = []
for index, screen_names in enumerate(screen_count):
resolution = screen_count[index].size()
height = resolution.height()
width = resolution.width()
resolutions_in_x.append(width)
low_resolution_monitors = {}
high_resolution_monitors = {}
for i, wid_res in enumerate(resolutions_in_x):
if wid_res > 1920:
high_resolution_monitors.update({i: wid_res})
else:
low_resolution_monitors.update({'L': wid_res})
temp_value = 0
high_res_monitors_x_position = []
low_res_monitors_x_position = []
for i in range(len(screen_count)):
temp_value = temp_value+resolutions_in_x[i]
if resolutions_in_x[i] in high_resolution_monitors.values():
high_res_monitors_x_position.append(temp_value-resolutions_in_x[i])
else:
low_res_monitors_x_position.append(temp_value-resolutions_in_x[i])
total_width_res = []
pixel_value = 0
first_pixel = 0
for i, wid_value in enumerate(resolutions_in_x):
pixel_value = pixel_value + wid_value
total_width_res.append(tuple((first_pixel, pixel_value-1)))
first_pixel = pixel_value
return high_res_monitors_x_position, low_res_monitors_x_position, total_width_res
def moveEvent(self, event):
screen_pos = self.pos()
screen_dimensions = [screen_pos.x(),screen_pos.y()]
super(MainWindow, self).moveEvent(event)
Window_starting_pt = screen_pos.x()
for i, value in enumerate(self.total_width_res):
if value[0]<=Window_starting_pt+30 <=value[1] or value[0]<=Window_starting_pt-30 <=value[1]: #taking 30pixels as tolerance since widgets are staring at some negative pixel values
if value[0] in self.high_res_monitors_x_position:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
else:
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, False)
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, False)
使用 aboe 的两个函数可以跟踪我的应用程序 (window) 位置并且还可以跟踪它何时被拖到 windows