[英]PyQt5 get pos of another widget?
我試圖將一個小部件pos()
(A)映射到另一個小部件(B),以便B可以根據A的位置進行一些工作。 我有WidgetA
來獲取WidgetB
pos,這些小部件可以具有不同的育兒層次結構:
Global
+--- Window
+--- WidgetA
+--- WidgetB
Global
+--- Window
+--- Sub
| +--- Sub
| +--- WidgetB
|
+--- WidgetA
Global
+--- Window
| +--- WidgetB
|
+--- WidgetA
等等
我試圖通過(兩個小部件共享同一個父對象)將B
的位置轉換為A
'上的相對位置:
WidgetB.setGeometry(150, 150, 100, 100)
# expected vs result
WidgetA.mapFromGlobal(WidgetB.mapToGlobal(WidgetB.pos())) # 150, 150 125, 200
WidgetA.mapFrom(WidgetA.parent, WidgetB.pos()) # 150, 150 -25, 50
WidgetA.parent.mapFromGlobal(WidgetB.mapToGlobal(WidgetB.pos())) # 150, 150 300, 300
進行此映射的正確方法是什么? 我似乎無法正確包裝它。
碼:
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5 import QtCore
import sys
class Window(QWidget):
def __init__(self, Parent=None):
super().__init__()
self.WidgetA = QWidget(self)
self.WidgetA.setAttribute(QtCore.Qt.WA_StyledBackground, True)
self.WidgetA.setObjectName("WidgetA")
self.WidgetA.setGeometry(400, 400, 100, 100)
self.WidgetB = QWidget(self)
self.WidgetB.setAttribute(QtCore.Qt.WA_StyledBackground, True)
self.WidgetB.setObjectName("WidgetB")
self.WidgetB.setGeometry(0, 0, 100, 100)
self.setGeometry(0, 0, 500, 500)
self.setStyleSheet("""
#WidgetA {
background-color: red;
}
#WidgetB {
background-color: blue;
}
""")
def resizeEvent(self, event):
print(self.WidgetB.pos())
print(self.WidgetA.pos())
print(self.WidgetA.mapFromGlobal(self.WidgetB.mapToGlobal(self.WidgetB.pos())))
print(self.WidgetA.mapFrom(self, self.WidgetB.pos()))
print(self.mapFromGlobal(self.WidgetB.mapToGlobal(self.WidgetB.pos())))
if __name__ == "__main__":
app = QApplication(sys.argv)
screen = Window()
screen.show()
sys.exit(app.exec_())
輸出:
PyQt5.QtCore.QPoint()
PyQt5.QtCore.QPoint(400, 400)
PyQt5.QtCore.QPoint(-400, -400)
PyQt5.QtCore.QPoint(-400, -400)
PyQt5.QtCore.QPoint()
我希望得到(0, 0)
因為這是WidgetB
設置的。
小部件的位置是相對於父級的,而不是相對於屏幕的位置,因此在您的示例中,您應該獲得(400, 400)
。
根據文檔 :
pos:QPoint
此屬性保存窗口小部件在其父窗口小部件內的位置
如果窗口小部件是窗口,則位置是桌面上窗口小部件(包括其框架)的位置。
更改位置時,小部件(如果可見)會立即接收一個移動事件(moveEvent())。 如果該窗口小部件當前不可見,則可以保證在顯示該事件之前會收到一個事件。
默認情況下,此屬性包含一個指向原點的位置。
有些方法似乎可行,但這是因為您已在(0, 0)
建立了父窗口小部件的位置,如果更改它,它將失敗。
考慮到您想要A相對於B的位置,解決方案如下:
使用以下方法獲取小部件B相對於屏幕的位置:
gp = self.WidgetB.mapToGlobal(QtCore.QPoint(0, 0))
它被傳遞(0, 0)
因為mapToGlobal
要求相對於使用該函數的小部件的位置,在您的情況下WidgetB
相對於WidgetB
的位置為(0, 0)
。
然后映射關於WidgetA
的全局位置:
b_a = self.WidgetA.mapFromGlobal(gp)
因此,以下示例顯示了我的解決方案的操作:
import sys
from random import randint
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.WidgetA = QtWidgets.QWidget(self)
self.WidgetA.resize(100, 100)
self.WidgetA.setAttribute(QtCore.Qt.WA_StyledBackground, True)
self.WidgetA.setObjectName("WidgetA")
self.WidgetB = QtWidgets.QWidget(self)
self.WidgetB.resize(100, 100)
self.WidgetB.setAttribute(QtCore.Qt.WA_StyledBackground, True)
self.WidgetB.setObjectName("WidgetB")
self.posA = QtCore.QPoint(randint(0, self.width()-100), randint(0, self.height()-100))
self.posB = QtCore.QPoint(randint(0, self.width()), randint(0, self.height()))
self.WidgetA.move(self.posA)
self.WidgetB.move(self.posB)
self.setStyleSheet("""
#WidgetA {
background-color: red;
}
#WidgetB {
background-color: blue;
}
""")
self.WidgetA.installEventFilter(self)
self.WidgetB.installEventFilter(self)
self.installEventFilter(self)
def eventFilter(self, obj, event):
if obj in (self.WidgetA, self.WidgetB, self) and event.type() in (QtCore.QEvent.Resize, QtCore.QEvent.Move) :
gp = self.WidgetB.mapToGlobal(QtCore.QPoint(0, 0))
b_a = self.WidgetA.mapFromGlobal(gp)
print(b_a, self.posB -self.posA)
assert(b_a == (self.posB -self.posA))
return QtWidgets.QWidget.eventFilter(self, obj, event)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.