当点击 QPushButton 时,它会触发两次

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

我在一个项目中使用了 PyQt5,并有以下代码片段(

button
是一个 QPushButton)

def on_receive(self, query):
    print("receiving", query)
    datapackages = json.loads(query)

    for button, datapackage in zip(self.buttonArray, datapackages):
        self.wire_up_button(datapackage, button) 

def wire_up_button(self, datapackage, button):
    title, songid = datapackage["title"], datapackage["songid"]
    button.setText(title + " (" + str(datapackage["votes"]) + ")")
    button.clicked.connect(lambda: self.upvote(songid))

def upvote(self, sid):
    text = '{"action":"upvote", "value":"' + sid + '"}\n'
    print(text)
    self.send(text)

def send(self, text):
    print("Sending")

on_receive
函数连接到socket客户端,每当收到数据包时就会调用。布局有点复杂,因为我的 UI 有太多按钮,迭代它们比对每个按钮进行硬编码更方便。

每当我单击按钮时,连接函数都会将按钮连接到 upvote 函数,该函数创建一个 json 协议并将其发送到套接字服务器。但是,每次点击都会调用连接功能 twice。 (由于调试打印命令,我确信这一点)。我的程序中的发送函数中没有其他调用。

我推测这可能是由于 clicked.connect 的工作方式造成的(也许它在单击 释放时触发)。

我使用 QtDesigner 创建 UI 并将

.uic
加载到我的
main.py

python pyqt5 qt-designer qpushbutton
2个回答
4
投票

每次你从套接字收到任何东西时

for button, datapackage in zip(self.buttonArray, datapackages):
    self.wire_up_button(datapackage, button)

并在

self.wire_up_button
中连接到按钮单击事件。请注意,
self.buttonArray
始终是相同的按钮列表,因此每次调用
on_receive
时,您都会为每次按钮单击添加 1 个新订阅。但之前对按钮点击的订阅仍然存在,因此按钮点击时
upvote
将被多次调用,并具有不同的
sid
。在添加新按钮之前,您需要断开与按钮单击事件的连接:

def wire_up_button(self, datapackage, button):
    try:
        button.clicked.disconnect()
    except:
        pass
    title, songid = datapackage["title"], datapackage["songid"]
    button.setText(title + " (" + str(datapackage["votes"]) + ")")
    button.clicked.connect(lambda: self.upvote(songid))

try ... except
块是必需的,因为如果没有函数连接到单击事件,
button.clicked.disconnect()
会引发异常。


0
投票

就我而言,我的按钮的

clicked
事件触发了两次,这可以通过非常简单的步骤修复:记住添加
@pyqtSlot
装饰器

QMetaObject.connectSlotsByName
pyuic
创建的 Ui 脚本中仅被调用一次,但使用以下代码:

def on_testBtn_clicked(self):
    print('on_testBtn_clicked')

名为

QPushButton
testBtn
上的单击事件被调用了两次。使用此代码:

from PyQt5.QtCore import pyqtSlot

@pyqtSlot()
def on_testBtn_clicked(self):
    log.debug('on_testBtn_clicked')

它正确地只被调用了一次。

self.testBtn.dumpObjectInfo()
可能有助于检查连接了多少个插槽。没有装饰器我得到:

OBJECT QPushButton::testBtn
  SIGNALS OUT
        signal: destroyed(QObject*)
          <functor or function pointer>
          --> PyQtSlotProxy::unnamed disable()
          --> PyQtSlotProxy::unnamed disable()
        signal: clicked(bool)
          --> PyQtSlotProxy::unnamed unislot()
          --> PyQtSlotProxy::unnamed unislot()
  SIGNALS IN
        <None>

与装饰器:

OBJECT QPushButton::testBtn
  SIGNALS OUT
        signal: destroyed(QObject*)
          <functor or function pointer>
        signal: clicked(bool)
          --> MainWindow::MainWindow on_testBtn_clicked()
  SIGNALS IN
        <None>
© www.soinside.com 2019 - 2024. All rights reserved.