获取光标下的所有小部件 [英] Get all widgets under cursor

查看:117
本文介绍了获取光标下的所有小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

widgetAt 函数为我提供了光标正下方的小部件,位于最高 z 顺序.

The widgetAt function gives me the widget directly under the cursor, at the highest z-order.

pos = QtGui.QCursor.pos()
widget = QtGui.qApp.widgetAt(pos)

但是我怎样才能在光标下获得所有小部件?包括最上面的那些?类似的东西:

But how can I get all widgets under the cursor? Including those behind the top-most one? Something like:

pos = QtGui.QCursor.pos()
widgets = QtGui.qApp.widgetsAt(pos)

示例

作为一个使用示例,绘制一个叠加层,在用户点击的任何位置添加动画图形,例如水面上的涟漪.当然,叠加层需要接收和响应点击,但它必须在不干扰传播到其下方小部件的点击的情况下进行.

Example

As an example of use, picture an overlay which adds animated graphics, like ripples on the surface of water, wherever the user clicked. Naturally, the overlay would need to receive and respond to clicks, but it must do so without interfering with clicks propagating to widgets underneath it.

另一个例子是使用情况跟踪;拦截和记录点击进行分析,可以使用相同的叠加层,但这次什么都不绘制,只收集.

Another example is usage tracking; to intercept and record clicks for analysis, the same overlay can be used but this time nothing is drawn, only collected.

在这两种情况下,如果只有一个小部件获得点击事件,我需要一种方法来区分哪些小部件驻留在它下面以便传递事件.

In both cases, if only one widget is getting the click event, I'll need a way of distinguishing what widgets reside underneath it so as to pass the event on.

推荐答案

这是另一种可能的解决方案,多次调用现有的 QApplication.widgetAt.

Here's another possible solution, calling the existing QApplication.widgetAt multiple times.

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

示例

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_()

这是一些输出.

[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

看起来结果是 O(1),另外的好处是按照它们重叠的顺序返回每个小部件.然而,当它们的属性被更改和恢复时,它会导致重叠窗口闪烁(Windows 8).

It looks like the results are O(1), with the added benefit of returning each widget in the order in which they overlap. It does however cause overlapping windows to flash (Windows 8) as their attribute is changed and restored.

这篇关于获取光标下的所有小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆