2017-10-14 7 views
1

j'ai utilisé PyQt5 pour un projet et l'extrait de code suivant (button est un QPushButton)Lorsqu'un QPushButton est cliqué, il se déclenche deux fois

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") 

La fonction on_receive est connecté à un client soccet et sera appelé wheneever un paquet de données est reçu. La mise en page est un peu compliquée parce que mon interface utilisateur a tellement de boutons qu'il est plus pratique de les parcourir que de coder en dur chacun d'entre eux.

Chaque fois que je clique sur le bouton, la fonction de branchement câble le bouton à la fonction upvote, qui crée un protocole json et l'envoie au serveur socket. Cependant, la fonction wireup est appelée deux fois par clic. (J'en suis certain à cause des commandes d'impression de débogage). Il n'y a pas d'autre appel dans la fonction d'envoi de mon programme.

Je spécule que cela peut être dû à la façon dont clicked.connect fonctionne (peut-être qu'il se déclenche au clic et version).

J'ai utilisé le QtDesigner pour créer l'interface utilisateur et chargé le .uic dans mon main.py

+0

s'il vous plaît, pourriez-vous ajouter plus de contexte, comme où se trouve la ligne de signal 'connect'? en voyant 'songid' il semble que ce soit dans une fonction – PRMoureu

+1

@PRMoureu Je l'ai fait, cela pourrait obscurcir ce qui s'y passe un peu. J'ai essayé de mon mieux pour le rendre aussi lisible que possible ... – Narusan

+1

est-ce que upvote() a appelé avec le même sid? Êtes-vous sûr de ne pas appeler deux fois Wire_up_button pour le même bouton? – ingvar

Répondre

1

Chaque fois que vous recevez quelque chose de socket vous

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

et self.wire_up_button vous vous connectez à bouton événement cliqué. Notez que self.buttonArray est toujours la même liste de boutons, donc à chaque fois que on_receive est appelée, vous ajoutez 1 nouvel abonnement à chaque clic de bouton. Mais l'abonnement précédent au clic sur le bouton existe toujours, donc sur le bouton, le bouton upvote sera appelé plusieurs fois avec différents sid. Vous devez vous déconnecter de bouton événement click avant d'ajouter nouveau:

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 bloc est nécessaire, car button.clicked.disconnect() soulève exception si aucune fonction ont été connectés à cliquer sur l'événement.