gpt4 book ai didi

python - QMenu 无法正确执行方法

转载 作者:行者123 更新时间:2023-12-01 00:24:59 25 4
gpt4 key购买 nike

我正在使用一个执行一些方法的自定义 QMenu。该菜单具有三个选项:删除行选项、切换变量选项和调试选项(打印切换变量的值)。代码未正确执行。有时调试按钮不起作用,它会突然被执行多次。切换选项需要单击两次才能工作,我不知道为什么。这是我的 MRE:

# -*- coding: utf-8 -*-

from PyQt5.QtCore import Qt, QRect, pyqtSlot
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QWidget, QPushButton, QHBoxLayout, QMainWindow, QLabel, QMenu, \
QApplication, QVBoxLayout, QListWidgetItem, QListWidget, QAction


class Punto(QWidget):
def __init__(self, parent, internal_id, name):
QWidget.__init__(self)

# Toggle variable
self.render = True

self.customContextMenuRequested.connect(self.context_menu)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.menu = QMenu()
self.borrar = QAction("Delete")
self.ver = QAction("Toggle")
self.debug = QAction("Debug")
self.ver.setCheckable(True)
self.ver.setChecked(True)

self.parent = parent
self.id = internal_id

label = QLabel(name)
hbox = QHBoxLayout()
hbox.addWidget(label)
hbox.addStretch(1)
self.setLayout(hbox)

def context_menu(self):
self.menu.addAction(self.borrar)
self.borrar.triggered.connect(self.delete)

self.menu.addAction(self.ver)
self.ver.triggered.connect(self.change)

self.menu.addAction(self.debug)
self.debug.triggered.connect(self.debugg)

self.menu.exec(QCursor.pos())

@pyqtSlot()
def debugg(self):
print(f"Render: {self.render}")

@pyqtSlot()
def change(self):
if self.ver.isChecked():
self.ver.setChecked(False)
self.render = False
else:
self.ver.setChecked(True)
self.render = True

@property
def itemid(self):
return self.id

@pyqtSlot()
def delete(self):
self.parent.delete_point(self.id)


class Ventana(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setFixedSize(200, 200)

widget_central = QWidget(self)

boton_punto = QPushButton(widget_central)
boton_punto.setGeometry(QRect(0, 0, 200, 20))
boton_punto.clicked.connect(self.crear_punto)

boton_punto.setText("Create")

widget_punto = QWidget(widget_central)
widget_punto.setGeometry(QRect(0, 20, 200, 200))
vertical_punto = QVBoxLayout(widget_punto)
vertical_punto.setContentsMargins(0, 0, 0, 0)
self.lista_puntos = QListWidget(widget_punto)

vertical_punto.addWidget(self.lista_puntos)

self.id_punto = 0
self.setCentralWidget(widget_central)

def crear_punto(self):
# Add placeholder item to List
item = QListWidgetItem()
self.lista_puntos.addItem(item)
# Create Custom Widget
punto = Punto(self, self.id_punto, "A")
self.id_punto += 1
item.setSizeHint(punto.minimumSizeHint())
# Set the punto widget to be displayed within the placeholder item
self.lista_puntos.setItemWidget(item, punto)

def delete_point(self, idd):
for indx in range(self.lista_puntos.count()):
item = self.lista_puntos.item(indx)
widget = self.lista_puntos.itemWidget(item)
if widget.id == idd:
self.lista_puntos.takeItem(self.lista_puntos.row(item))
break


if __name__ == "__main__":
MainEvent = QApplication([])
main_app = Ventana()
main_app.show()
MainEvent.exec()

最佳答案

您有 2 个错误:

  • 默认情况下,QAction 已经进行了状态更改,因此您没有必要实现它,但您正在执行它,也就是说,默认情况下 QAction 从开变为关(反之亦然),但是您通过代码将其从关闭更改为打开(反之亦然),当在毫秒内完成时,不会观察到更改。因此,不要连接触发信号,而是使用切换信号并更改渲染。

  • 当您将信号连接到同一个插槽“n”次,该插槽被调用“n”次,并且在您的情况下,每次调用 context_menu 方法时都连接它,至少有 2 种解决方案:仅建立一次连接或使用连接类型 Qt::UniqueConnection,在我的解决方案中我将使用第一个。

考虑到上述情况,解决方案是:

class Punto(QWidget):
def __init__(self, parent, internal_id, name):
QWidget.__init__(self)

# Toggle variable
self.render = True

self.customContextMenuRequested.connect(self.context_menu)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.menu = QMenu()
self.borrar = QAction("Delete")
self.ver = QAction("Toggle")
self.debug = QAction("Debug")
self.ver.setCheckable(True)
self.ver.setChecked(True)

self.parent = parent
self.id = internal_id

label = QLabel(name)
hbox = QHBoxLayout(self)
hbox.addWidget(label)
hbox.addStretch(1)

self.borrar.triggered.connect(self.delete)
self.ver.toggled.connect(self.change)
self.debug.triggered.connect(self.debugg)
self.menu.addAction(self.borrar)
self.menu.addAction(self.ver)
self.menu.addAction(self.debug)

def context_menu(self):
self.menu.exec(QCursor.pos())

@pyqtSlot()
def debugg(self):
print(f"Render: {self.render}")

@pyqtSlot(bool)
def change(self, state):
self.render = self.ver.isChecked()

@property
def itemid(self):
return self.id

@pyqtSlot()
def delete(self):
self.parent.delete_point(self.id)

关于python - QMenu 无法正确执行方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58658628/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com