web-dev-qa-db-fra.com

Comment déterminer un écran (moniteur) actif de mon application (fenêtre) en utilisant python PyQt5?

Je travaille sur une application qui utilise de nombreux widgets (QGroupBox, QVBoxLayout, QHBoxLayout). Initialement, il a été développé sur des moniteurs HD normaux. Mais, récemment, beaucoup d'entre nous sont passés à des moniteurs à résolution 4K. Maintenant, certains des boutons et curseurs sont compressés si petits qu'ils sont inutilisables.

Maintenant, j'ai essayé de faire quelques changements pour que l'application puisse être utilisée avec les moniteurs HD et 4K.

J'ai commencé à lire le lien ci-dessous:

https://leomoon.com/journal/python/high-dpi-scaling-in-pyqt5/entrez la description du lien ici

J'ai pensé que chaque fois que ma fenêtre est ouverte dans un moniteur particulier, je peux appeler le code suivant:

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)

Ensuite, j'ai essayé d'obtenir la résolution du moniteur (pixel_x et pixel_y) en utilisant le code ci-dessous en utilisant la publication associée ici .

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 me donne la résolution de mon moniteur principal (principalement des ordinateurs portables dans notre cas qui sont en HD). screen_width = 78, screen_height = 79 me donne la résolution combinée des machines virtuelles. Mais je ne comprends pas comment je peux obtenir dynamiquement ces valeurs selon l'endroit où mon application s'est ouverte.

Ma fenêtre d'application est développée de telle manière qu'elle s'ouvrira dans le même moniteur où elle a été fermée la dernière fois. Le problème est maintenant que je veux obtenir la résolution active du moniteur chaque fois que mon interface graphique est appelée et m'adapter à cette résolution. Je serais heureux si quelqu'un pouvait m'aider.

Je suis intéressé de savoir si je peux appeler le calcul de la résolution d'écran chaque fois que je fais glisser ma fenêtre d'un moniteur HD vers un moniteur 4K et vice versa.

Edit: J'ai trouvé quelque chose de similaire dans cet article ici Mais je n'ai pas pu en tirer grand-chose.

Edit2: Basé sur la solution @Joe, détection d'écran primaire, pourquoi mon écran principal est-il toujours la résolution de mon ordinateur portable même si je lance l'application sur un écran 4K? enter image description here

J'ai juste essayé d'obtenir le dpi de tous les écrans en utilisant le code ci-dessous:

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
8
Rohithsai Sai

Eh bien, après avoir créé MainWindow, vous pouvez simplement appeler QMainWindow.screen () . Cela renvoie l'écran actuel sur lequel la fenêtre principale est allumée. Cela vous permettrait au moins de vérifier la résolution d'écran au début de votre application. À l'heure actuelle, il n'y a rien de tel qu'un screenChangeEvent. Cependant, je suis sûr que vous pouvez en créer un en sous-classant le MainWindow et en surchargeant le QMainWindow.moveEvent

Par exemple:

    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)

Ceci vérifie si l'écran a changé. S'il l'a, il émet un signal. Il ne vous reste plus qu'à connecter ce signal à une fonction qui définit vos attributs dpi. L'événement vous donne accès à l'ancien et au nouvel écran.

Avertissement:

L'un des écrans peut être None au début de votre application car il n'y a pas de oldScreen lorsque vous démarrez votre application pour la première fois. Veuillez donc vérifier ceci.

3
Tim Körner

Une solution que j'ai trouvée à travers est d'utiliser une QApplication() temporaire:

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 ...

Cette fonction détectera tous les écrans connectés:

# 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

Vous pouvez utiliser les astuces ici et ici pour obtenir l'écran sur lequel l'application s'exécute.

Mais je pense que primaryScreen devrait également retourner ceci:

primaryScreen: QScreen * const

Cette propriété contient l'écran principal (ou par défaut) de l'application.

Ce sera l'écran où QWindows sont initialement affichés, sauf indication contraire.

( https://doc.qt.io/qt-5/qguiapplication.html#primaryScreen-prop )

6
Joe

Bien que je n'aie pas pu obtenir la solution directe, je suis en mesure de développer une méthode pour obtenir ce que je cherchais. Avec l'aide de quelques liens et d'un article précédent, je suis en mesure d'atteindre. avec cet article J'ai eu une idée de suivre l'événement de la souris.

J'ai développé une méthode pour suivre tous les moniteurs et les positions de regard respectives. si mon nom de variable n'est pas approprié, je suis heureux d'accepter les modifications

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)

Avec aboe, deux fonctions sont capables de suivre la position de mon application (fenêtre) et également de suivre quand elle est glissée entre les fenêtres

3
Rohithsai Sai