Mar*_*son 5 qt pyqt pyqt4 pyside pyqt5
该widgetAt函数直接在光标下给出了小部件,位于最高的z顺序.
pos = QtGui.QCursor.pos()
widget = QtGui.qApp.widgetAt(pos)
Run Code Online (Sandbox Code Playgroud)
但是如何在光标下获取所有小部件?包括最顶端的那些?就像是:
pos = QtGui.QCursor.pos()
widgets = QtGui.qApp.widgetsAt(pos)
Run Code Online (Sandbox Code Playgroud)
作为一个使用示例,想象一个叠加层,它可以添加动画图形,如水面上的涟漪,无论用户点击何处.当然,叠加层需要接收并响应点击,但必须这样做,而不会干扰传播到其下方小部件的点击.
另一个例子是使用跟踪; 为了截取和记录点击进行分析,可以使用相同的叠加,但这次没有绘制,只收集.
在这两种情况下,如果只有一个小部件获得了click事件,我需要一种方法来区分它下面的小部件,以便传递事件.
这是另一种可能的解决方案,QApplication.widgetAt多次调用现有的解决方案.
import sys
from PySide import QtGui, QtCore
def widgets_at(pos):
"""Return ALL widgets at `pos`
Arguments:
pos (QPoint): Position at which to get widgets
"""
widgets = []
widget_at = QtGui.qApp.widgetAt(pos)
while widget_at:
widgets.append(widget_at)
# Make widget invisible to further enquiries
widget_at.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
widget_at = QtGui.qApp.widgetAt(pos)
# Restore attribute
for widget in widgets:
widget.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents, False)
return widgets
Run Code Online (Sandbox Code Playgroud)

class Overlay(QtGui.QWidget):
def __init__(self, parent=None):
super(Overlay, self).__init__(parent)
self.setAttribute(QtCore.Qt.WA_StyledBackground)
self.setStyleSheet("QWidget { background-color: rgba(0, 255, 0, 50) }")
def mousePressEvent(self, event):
pos = QtGui.QCursor.pos()
print [w.objectName() for w in widgets_at(pos)]
return super(Overlay, self).mousePressEvent(event)
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.setObjectName("Window")
window.setFixedSize(200, 100)
button = QtGui.QPushButton("Button 1", window)
button.setObjectName("Button 1")
button.move(10, 10)
button = QtGui.QPushButton("Button 2", window)
button.setObjectName("Button 2")
button.move(50, 15)
overlay = Overlay(window)
overlay.setObjectName("Overlay")
overlay.setFixedSize(window.size())
window.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)
这是一些输出.
[u'Overlay', u'Window'] # Clicking an empty area
[u'Overlay', u'Button 1', u'Window'] # Button 1
[u'Overlay', u'Button 2', u'Window'] # Button 2
[u'Overlay', u'Button 2', u'Button 1', u'Window'] # Overlap
Run Code Online (Sandbox Code Playgroud)
看起来结果是O(1),并且具有按照它们重叠的顺序返回每个小部件的额外好处.但是,它会导致重叠窗口闪烁(Windows 8),因为它们的属性已更改并恢复.
不太漂亮,但超出了我的想象:您需要循环浏览所有小部件并根据鼠标坐标使用它们的坐标。
如果您想要O(1),您可以这样做,但它将需要更多开销,并且您需要在每次移动后存储坐标。
我实际上有一个类可以做到这一点,因为我希望可移动(由用户)小部件以之前的状态出现,并且我不想在我的所有项目中经历编码的麻烦。
因此,我进行了子类化QDialog(等等),并将其添加到一个便利类中,该类本质上是一个美化的QSettings对象。
当QDialog发出任何有用的东西时,便利类的插槽会将这些值(geometry()基本上)存储在QSettings.
对于任何使用此行为的项目,ConvenienceClass::addWidget()只需使用QWidget, 和 aQString作为参数(作为键)进行简单的调用,它就全部存储在工作表下。
如果您想对此进行扩展,您可以将所有 的QWidget坐标存储在这个便利类中,并在您认为必要时简单地获取它们O(1) 。
坐标的存储是微不足道的,因为无论如何计算它们的工作已经完成。保存这些的便利类并不太困难,但确实增加了一些复杂性。