如何修复 python pyside 应用程序以检测所有监视器,同时将对象置于主监视器上

问题描述 投票:0回答:1

我想创建一个跨越所有显示器的窗口,在我的例子中,我有 3 个。该窗口是一个半透明背景,带有可拖动的正方形。该正方形用于为我的代码的不同部分提供位置。

当我使窗口跨越所有 3 个显示器时,在我的左边创建了一个正方形,这不是我的主要显示器,并且位置对应得不好。当我更改代码并仅将焦点放在主屏幕上时,一切正常,但背景不再跨越所有 3 个显示器。

以下代码中所有 3 个显示器都有背景,并且方块放置不正确。我想要跨越所有 3 个显示器的效果,但不是放置不当的方块。

class DynamicAlignmentWindow(QWidget):
    positionSelected = Signal(int, int)

    def __init__(self, main_window, width, height):
        super().__init__()
        self.main = main_window
        self.main.hide()

        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.setWindowOpacity(0.5)
        self.setStyleSheet("background-color: rgba(0, 0, 255, 38);")

        # Set the geometry to span all monitors
        total_screen_rect = calculate_total_geometry()
        self.setGeometry(total_screen_rect)

        # Get the geometry of the primary screen
        primary_screen_geometry = QApplication.primaryScreen().geometry()

        self.lastPosition = None  # Initialize last known position

        print(f"Total Screen Rect: {total_screen_rect}")  # Debugging output for total geometry
        print(f"Primary Screen Rect: {primary_screen_geometry}")  # Debugging output for primary screen

        # Calculate center position for the square on the primary screen
        center_x = primary_screen_geometry.x() + (primary_screen_geometry.width() - width) // 2
        center_y = primary_screen_geometry.y() + (primary_screen_geometry.height() - height) // 2
        print(f"Centering at: X={center_x}, Y={center_y}")  # Debugging output for centering

        # Initialize the square and center it on the primary screen
        self.rubber_band = QRubberBand(QRubberBand.Rectangle, self)
        self.rubber_band.setGeometry(QRect(QPoint(center_x, center_y), QSize(width, height)))
        self.rubber_band.show()

        self.dragging = False
        self.drag_position = QPoint()

我只想要这里的 3 台显示器背景。

Visual For clarity

这里是只有主监视器有背景并且方块放置正确的代码。我希望所有 3 个显示器都具有像上面示例一样的背景,但是这个方形位置。

class DynamicAlignmentWindow(QWidget):
    positionSelected = Signal(int, int)

    def __init__(self, main_window, width, height):
        super().__init__()
        self.main = main_window
        self.main.hide()

        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.setWindowOpacity(0.5)
        self.setStyleSheet("background-color: rgba(0, 0, 255, 38);")

        primary_screen_geometry = QApplication.primaryScreen().geometry()
        self.setGeometry(primary_screen_geometry)

        self.lastPosition = None  # Initialize last known position

        print(f"Primary Screen Rect: {primary_screen_geometry}")  # Debugging output

        center_x = primary_screen_geometry.x() + (primary_screen_geometry.width() - width) // 2
        center_y = primary_screen_geometry.y() + (primary_screen_geometry.height() - height) // 2
        print(f"Centering at: X={center_x}, Y={center_y}")  # More debugging output

        self.rubber_band = QRubberBand(QRubberBand.Rectangle, self)
        self.rubber_band.setGeometry(QRect(QPoint(center_x, center_y), QSize(width, height)))
        self.rubber_band.show()

        self.dragging = False
        self.drag_position = QPoint()

我只想知道这里正方形的位置。

Visual

我不认为下面的函数是问题所在,但我添加它以防它有助于解决这个问题:

查找所有屏幕的几何图形

def calculate_total_geometry():
    total_rect = QRect()
    for screen in QApplication.screens():
        total_rect = total_rect.united(screen.geometry())
    return total_rect

更新

当我使用下面的代码时,我相信我得到了正确的主屏幕。我得到:

总屏幕矩形:PySide6.QtCore.QRect(-1920, 0, 5760, 1081)

但是,这会将我最左边屏幕上的正方形居中,这不是我的主要屏幕。不过我不介意,后来这个位置就不对应了。我的应用程序使用选定的图像显示叠加层。当正方形位于左侧屏幕中央并且我更改其位置时,图像将向下覆盖一个屏幕。

例如,如果我将左上角的正方形放在左侧屏幕上,它会覆盖左上角中央屏幕。所以位置对应不正确。我不确定为什么会发生这种情况,但我认为如果我在主中心屏幕或用户主屏幕上生成正方形,则位置将正确对应。

self.lastPosition = None  # Initialize last known position

        self.setGeometry(calculate_total_geometry())
        total_screen_rect = calculate_total_geometry()
        print(f"Total Screen Rect: {total_screen_rect}")  # Debugging output

        center_x = total_screen_rect.x() + (total_screen_rect.width() - width) // 2
        center_y = total_screen_rect.y() + (total_screen_rect.height() - height) // 2
        print(f"Centering at: X={center_x}, Y={center_y}")  # More debugging output
python qt pyside
1个回答
0
投票

您需要更仔细地检查屏幕几何形状:根据您的输出,连接的矩形从-1920开始,表示全局坐标中的负x:而主屏幕从0开始,最左边的屏幕从-1920开始.

但是随后您使用主屏幕的相同几何形状作为相对坐标来获取中心的参考位置,这是错误的:小部件坐标始终相对于父级的左上角,而父级的左上角始终是

0, 0
,但是你的坐标系实际上应该考虑整个几何体,它具有负的全局位置。

为了获得准确的位置,您需要使用基于 0 的坐标来获取主屏幕的 translated 几何形状。

虽然您可以简单地添加左侧屏幕的宽度,但更合适的解决方案应该独立于屏幕布局工作,这样即使整个屏幕几何形状不从

0, 0
开始,它也能工作:它可能是负值,例如在你的情况下,但即使是积极的,如果你使用不同高度的屏幕,布局也可能有不同的垂直偏移。

# this may have an origin (top/left) different than 0, 0
total_screen_rect = calculate_total_geometry()
self.setGeometry(total_screen_rect)

# get the origin point of the screen geometry
origin = total_screen_rect.topLeft()

primary_screen_geometry = QApplication.primaryScreen().geometry()

# translate the geometry in "widget coordinates"; note the minus sign!
local_screen_geometry = primary_screen_geometry.translated(-origin)
center = local_screen_geometry.center()

self.rubber_band = QRubberBand(QRubberBand.Rectangle, self)
self.rubber_band.setGeometry(
    center.x() - width // 2, center.y() - height // 2, width, height)

请注意,执行

QRect(QPoint(x, y), QSize(w, h))
是没有意义的,因为 Qt 在内部会执行与
QRect(x, y, w, h)
相同的操作,从而使得 QPoint 和 QSize 对象的创建毫无意义;如果您在其他地方不需要该矩形,您甚至可以跳过 QRect 创建(如上所述),因为 Qt 无论如何都会使用
setGeometry(x, y, w, h)
重载来创建它。
另外,如果父级已经显示,您应该在子级小部件上调用
show()
only

© www.soinside.com 2019 - 2024. All rights reserved.