pyqt多个对象共享上下文菜单

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

因此,我对qt还是比较陌生,并且对python相当熟悉。但是,我有一个实例,我希望多个小部件(在这种情况下为标签)共享同一自定义上下文菜单,但我需要访问小部件的信息。

当我在每个标签上使用setContextMenuPolicycustomContextMenuRequested.connect时,尽管访问了带有第二个标签的上下文菜单,但我仅获得第一个标签的信息。

下面是我正在使用的精简版本:

from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QLabel
import sys


class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = "PyQt5 Context Menu"
        self.top = 200
        self.left = 500
        self.width = 200
        self.height = 100
        self.InitWindow()

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon("icon.png"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.firstLabel = QLabel(self)
        self.firstLabel.setText("Meep!")
        self.firstLabel.setObjectName("firstLabel")
        self.firstLabel.setStyleSheet("background-color: rgb(252, 233, 79);")

        self.firstLabel.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.firstLabel.customContextMenuRequested.connect(self.customMenuEvent)

        self.firstLabel.setGeometry(QtCore.QRect(0,0,50,30))


        self.secondLabel = QLabel(self)
        self.secondLabel.setText("Peem!")
        self.secondLabel.setObjectName("secondLabel")
        self.secondLabel.setStyleSheet("background-color: rgb(79,233, 252);")

        self.secondLabel.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.secondLabel.customContextMenuRequested.connect(self.customMenuEvent)

        self.secondLabel.setGeometry(QtCore.QRect(80,40,50,30))

        print("FIRST:", self.firstLabel)
        print("SECOND:", self.secondLabel)

        self.show()

    def customMenuEvent(self, eventPosition):
        child = self.childAt(eventPosition)
        print(child)
        contextMenu = QMenu(self)
        getText = contextMenu.addAction("Text")
        getName = contextMenu.addAction("Name")
        quitAct = contextMenu.addAction("Quit")
        action = contextMenu.exec_(self.mapToGlobal(eventPosition))

        if action == getText:
            print(child.text())

        if action == getName:
            print(child.objectName())

        if action == quitAct:
            self.close()



App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
python pyqt5 contextmenu
1个回答
0
投票

摘自有关customContextMenuRequested(pos)信号的文档:

位置pos是小部件接收的上下文菜单事件的位置

这意味着您将始终收到鼠标位置相对于触发信号的小部件

您正在使用customContextMenuRequested(pos),它相对于父级几何图形,但是由于提供的位置是相对于子级小部件的,因此您总是以相对于父级左上角的坐标结尾。

如果您尝试将第一个小部件的几何形状设置在左上角以外的位置,这将变得很清楚:即使右键单击第一个小部件,您也会看到菜单not显示在您单击的位置。如果仔细观察,还会根据父上左上角的坐标看到菜单完全显示在您单击的位置。

为了简单起见,一个简单的解决方案是将坐标从“ QWidget.childAt()”(发射接收器收到的最后一个信号的对象)映射到其父对象:

sender

但是要注意,这可能会导致一些不一致,尤其是在处理多线程时(因为从理论上讲,另一个线程可能在接收者实际接收到的那一刻触发了另一个信号之间右键单击事件 )。

有各种不同的方法可以避免这种情况,但是IT很大程度上取决于您如何构造程序。

例如,您可以使用lambda添加一个参数,以帮助标识从其发送事件的来源:

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