我正在使用 Manjaro(Arch) 和 3 个头 (3x1),我遇到了 PyQT 的问题。
我正在构建一个模块化应用程序,用户应该能够在其中将窗口调整为他们喜欢的任何可用大小。
然而,当一个窗口与两个屏幕重叠并调整大小(setGeometry()/resize())时,它会捕捉到它最覆盖的屏幕的 X 轴 0 坐标。
然而,这种行为似乎只发生在一些 sizegrips 上,我用#Affected # 标记了它们。
我偶然发现了一个临时修复程序(不要问我它是如何工作的),我已将其包含在受影响的 sizegrips 中,它们被标记为#Workaround #。
这是一个最小的例子,我不得不删掉一堆东西,如果它不完美,我们深表歉意:
import sys
import time
from PyQt6.QtCore import *
from PyQt6.QtWidgets import *
from PyQt6.QtGui import *
# Helpers #
def GridSnap(Value=int):
ScreenHeight = 1440
Divider = 36 # 36
Step = ScreenHeight/Divider
Value = int(Step*round(Value/Step))
return Value
class Container(QFrame):
def __init__(self,Parent):
super().__init__()
# Variables #
self.Parent = Parent
# Container #
self.setSizePolicy(QSizePolicy.Policy.Expanding,QSizePolicy.Policy.Expanding)
# Style #
self.setStyleSheet(
'Container { '
'background-color:blue; }')
def mousePressEvent(self,event):
if event.button() == Qt.MouseButton.LeftButton:
Event = event
EventX = GridSnap(Event.globalPosition().x())
EventY = GridSnap(Event.globalPosition().y())
EventPos = QPoint(EventX,EventY)
self.StartPos = EventPos
def mouseDoubleClickEvent(self,event):
if event.button() == Qt.MouseButton.LeftButton:
self.window().MaximizeNormal()
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
CursorY = GridSnap(Cursor.pos().y())
CursorPos = QPoint(CursorX,CursorY)
Screens = Application.screens()
DesktopWidth = sum([Screen.geometry().width() for Screen in Screens])
DesktopHeight = max([Screen.geometry().height() for Screen in Screens])
StartX = GridSnap(self.StartPos.x())
StartY = GridSnap(self.StartPos.y())
DeltaX = CursorX-StartX
DeltaY = CursorY-StartY
# X #
if (WindowX+WindowWidth)+DeltaX > DesktopWidth\
or WindowX+DeltaX < 0:
NewX = WindowX
else:
NewX = WindowX+DeltaX
# Y #
if (WindowY+WindowHeight)+DeltaY > DesktopHeight\
or WindowY+DeltaY < 0:
NewY = WindowY
else:
NewY = WindowY+DeltaY
# Window #
if (WindowX,WindowY) == (NewX,NewY):
return
else:
Window.move(NewX,NewY)
time.sleep(0.009)
self.StartPos = QPoint(CursorX,CursorY)
# Level 03 #
class Window(QFrame):
def __init__(self,Parent):
super().__init__()
# Variables #
self.Parent = Parent
self.IContainer = Container(self)
# Window #
self.setWindowTitle('Phantom Move')
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
self.setMinimumWidth(GridSnap(720))
self.setMinimumHeight(GridSnap(480))
class NorthWest(QSizeGrip):
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# NorthWest #
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Fixed)
self.setFixedWidth(4)
self.setFixedHeight(4)
# Style #
self.setStyleSheet('NorthWest { '
'background-color:red; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinWidth = GridSnap(Window.minimumWidth())
WindowMinHeight = GridSnap(Window.minimumHeight())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
CursorY = GridSnap(Cursor.pos().y())
CursorPos = QPoint(CursorX,CursorY)
GripPos = QPoint(WindowX,WindowY)
GripX = GripPos.x()
GripY = GripPos.y()
DeltaX = GripX-CursorX
DeltaY = GripY-CursorY
# X #
if WindowWidth+DeltaX < WindowMinWidth:
NewX = WindowX
NewWidth = WindowWidth
else:
NewX = CursorX
NewWidth = WindowWidth+DeltaX
# Y #
if WindowHeight+DeltaY < WindowMinHeight:
NewY = WindowY
NewHeight = WindowHeight
else:
NewY = CursorY
NewHeight = WindowHeight+DeltaY
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight)
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.INorthWest = NorthWest(self,self)
class North(QSizeGrip):
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# North #
self.setSizePolicy(QSizePolicy.Policy.Expanding,QSizePolicy.Policy.Fixed)
self.setFixedHeight(4)
# Style #
self.setStyleSheet('North { '
'background-color:#0d0e0f; }')
def paintEvent(self,event):
QSizeGrip.paintEvent(self,event)
self.setCursor(Qt.CursorShape.SizeVerCursor)
self.setStyleSheet('North { '
'background-color:orange; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinHeight = GridSnap(Window.minimumHeight())
Cursor = QCursor
CursorY = GridSnap(Cursor.pos().y())
GripY = WindowY
DeltaY = GripY-CursorY
# X #
NewX = WindowX
NewWidth = WindowWidth
# Y #
if WindowHeight+DeltaY < WindowMinHeight:
return
else:
NewY = WindowY-DeltaY
NewHeight = WindowHeight+DeltaY
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight)
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.INorth = North(self,self)
class NorthEast(QSizeGrip): # Affected #
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# NorthEast #
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Fixed)
self.setFixedWidth(4)
self.setFixedHeight(4)
# Style #
self.setStyleSheet('NorthEast { '
'background-color:red; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinWidth = GridSnap(Window.minimumWidth())
WindowMinHeight = GridSnap(Window.minimumHeight())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
CursorY = GridSnap(Cursor.pos().y())
CursorPos = QPoint(CursorX,CursorY)
GripPos = QPoint(WindowX+WindowWidth,WindowY)
GripX = GripPos.x()
GripY = GripPos.y()
DeltaX = CursorX-GripX
DeltaY = CursorY-GripY
# X #
if WindowWidth+DeltaX < WindowMinWidth:
NewX = WindowX
NewWidth = WindowWidth
else:
NewX = WindowX
NewWidth = WindowWidth+DeltaX
# Y #
if WindowHeight-DeltaY < WindowMinHeight:
NewY = WindowY
NewHeight = WindowHeight
else:
NewY = CursorY
NewHeight = WindowHeight-DeltaY
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight) # Workaround #
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.INorthEast = NorthEast(self,self)
class East(QSizeGrip): # Affected #
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# East #
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Expanding)
self.setFixedWidth(4)
# Style #
self.setStyleSheet('East { '
'background-color:orange; }')
def paintEvent(self,event):
QSizeGrip.paintEvent(self,event)
self.setCursor(Qt.CursorShape.SizeHorCursor)
self.setStyleSheet('East { '
'background-color:orange; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinWidth = GridSnap(Window.minimumWidth())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
GripX = WindowX+WindowWidth
DeltaX = GripX-CursorX
# X #
if WindowWidth-DeltaX < WindowMinWidth:
return
else:
NewX = WindowX
NewWidth = WindowWidth-DeltaX
# Y #
NewY = WindowY
NewHeight = WindowHeight
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight) # Workaround #
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.IEast = East(self,self)
class SouthEast(QSizeGrip): # Affected #
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# SouthEast #
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Fixed)
self.setFixedWidth(4)
self.setFixedHeight(4)
# Style #
self.setStyleSheet('SouthEast { '
'background-color:red; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinWidth = GridSnap(Window.minimumWidth())
WindowMinHeight = GridSnap(Window.minimumHeight())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
CursorY = GridSnap(Cursor.pos().y())
CursorPos = QPoint(CursorX,CursorY)
GripPos = QPoint(WindowX+WindowWidth,WindowY+WindowHeight)
GripX = GripPos.x()
GripY = GripPos.y()
DeltaX = GripX-CursorX
DeltaY = GripY-CursorY
# X #
if WindowWidth-DeltaX < WindowMinWidth:
NewX = WindowX
NewWidth = WindowWidth
else:
NewX = WindowX
NewWidth = WindowWidth-DeltaX
# Y #
if WindowHeight-DeltaY < WindowMinHeight:
NewY = WindowY
NewHeight = WindowHeight
else:
NewY = WindowY
NewHeight = WindowHeight-DeltaY
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight) # Workaround #
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.ISouthEast = SouthEast(self,self)
class South(QSizeGrip): # Affected #
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# South #
self.setSizePolicy(QSizePolicy.Policy.Expanding,QSizePolicy.Policy.Fixed)
self.setFixedHeight(4)
# Style #
self.setStyleSheet('South { '
'background-color:orange; }')
def paintEvent(self,event):
QSizeGrip.paintEvent(self,event)
self.setCursor(Qt.CursorShape.SizeVerCursor)
self.setStyleSheet('South { '
'background-color:orange; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinHeight = GridSnap(Window.minimumHeight())
Cursor = QCursor
CursorY = GridSnap(Cursor.pos().y())
GripY = WindowY+WindowHeight
DeltaY = GripY-CursorY
# Y #
NewX = WindowX
NewWidth = WindowWidth
# Y #
if WindowHeight-DeltaY < WindowMinHeight:
return
else:
NewY = WindowY
NewHeight = WindowHeight-DeltaY
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight) # Workaround #
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.ISouth = South(self,self)
class SouthWest(QSizeGrip): # Affected #
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# SouthWest #
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Fixed)
self.setFixedWidth(4)
self.setFixedHeight(4)
# Style #
self.setStyleSheet('SouthWest { '
'background-color:red; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinWidth = GridSnap(Window.minimumWidth())
WindowMinHeight = GridSnap(Window.minimumHeight())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
CursorY = GridSnap(Cursor.pos().y())
CursorPos = QPoint(CursorX,CursorY)
GripPos = QPoint(WindowX,WindowY+WindowHeight)
GripX = GripPos.x()
GripY = GripPos.y()
DeltaX = CursorX-GripX
DeltaY = CursorY-GripY
# X #
if WindowWidth-DeltaX < WindowMinWidth:
NewX = WindowX
NewWidth = WindowWidth
else:
NewX = CursorX
NewWidth = WindowWidth-DeltaX
# Y #
if WindowHeight+DeltaY < WindowMinHeight:
NewY = WindowY
NewHeight = WindowHeight
else:
NewY = WindowY
NewHeight = WindowHeight+DeltaY
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
#Window.setGeometry(NewX+1,NewY+1,NewWidth,NewHeight) # Workaround #
#time.sleep(0.009)
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.ISouthWest = SouthWest(self,self)
class West(QSizeGrip):
def __init__(self,Window,Parent):
super().__init__(Window)
# Variables #
self.Parent = Parent
# West #
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Expanding)
self.setFixedWidth(4)
# Style #
self.setStyleSheet('West { '
'background-color:orange; }')
def paintEvent(self,event):
QSizeGrip.paintEvent(self,event)
self.setCursor(Qt.CursorShape.SizeHorCursor)
self.setStyleSheet('West { '
'background-color:orange; }')
def mouseMoveEvent(self,event):
Window = self.window()
WindowX = GridSnap(Window.pos().x())
WindowY = GridSnap(Window.pos().y())
WindowPos = QPoint(WindowX,WindowY)
WindowWidth = GridSnap(Window.width())
WindowHeight = GridSnap(Window.height())
WindowMinWidth = GridSnap(Window.minimumWidth())
Cursor = QCursor
CursorX = GridSnap(Cursor.pos().x())
GripX = WindowX
DeltaX = GripX-CursorX
# X #
if WindowWidth+DeltaX < WindowMinWidth:
return
else:
NewX = WindowX-DeltaX
NewWidth = WindowWidth+DeltaX
# Y #
NewY = WindowY
NewHeight = WindowHeight
# Window #
if (WindowX,WindowY,WindowWidth,WindowHeight) == (NewX,NewY,NewWidth,NewHeight):
return
else:
Window.setGeometry(NewX,NewY,NewWidth,NewHeight)
time.sleep(0.009)
self.IWest = West(self,self)
class Layout(QGridLayout):
def __init__(self,Parent):
super().__init__()
# Variables #
self.Parent = Parent
# Layout #
self.setSpacing(0)
self.setContentsMargins(0,0,0,0)
self.addWidget(Parent.IContainer,1,1)
self.addWidget(Parent.INorthWest,0,0)
self.addWidget(Parent.INorth,0,1)
self.addWidget(Parent.INorthEast,0,2)
self.addWidget(Parent.IEast,1,2)
self.addWidget(Parent.ISouthEast,2,2)
self.addWidget(Parent.ISouth,2,1)
self.addWidget(Parent.ISouthWest,2,0)
self.addWidget(Parent.IWest,1,0)
self.ILayout = Layout(self)
self.setLayout(self.ILayout)
def mouseEvent(self,event):
print('Window Mouse')
return
def resizeEvent(self,event):
print('Window Resize')
return
def mouseMoveEvent(self,event):
print('Window MouseMove')
return
def moveEvent(self,event):
print('Window Move')
return
def dragMoveEvent(self,event):
print('Window dragMove')
return
def MaximizeNormal(self):
if self.windowState() == Qt.WindowState.WindowNoState:
self.setWindowState(Qt.WindowState.WindowMaximized)
for Child in self.children():
if isinstance(Child,QSizeGrip):
Child.setEnabled(False)
elif self.windowState() == Qt.WindowState.WindowMaximized:
self.setWindowState(Qt.WindowState.WindowNoState)
for Child in self.children():
if isinstance(Child,QSizeGrip):
Child.setEnabled(True)
class Application(QApplication):
def __init__(self,argv):
super().__init__(argv)
self.IWindow = Window(self)
self.IWindow.show()
self.IWindow.move(GridSnap(self.IWindow.pos().x()),GridSnap(self.IWindow.pos().y())) # Snap to Center #
IApplication = Application(sys.argv)
sys.exit(Application.exec())
任何帮助将不胜感激......
编辑:解决方法作为当前代码的补充,只需取消注释...保持其他 setGeometry/sleep 调用不变。