Не выполняется lambda QAction

Собственно. Если тот же самый экшн добавлять не в функции, а в цикле создания виджета, например - всё работает. Но мне нужно добавить этот экшн именно на результат функции.

К слову, если добавлять экшн без лямбды, а просто какой нибудь triggered.connect(label.hide) - то работает как надо.

import sys
from PyQt5 import QtWidgets,  QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QAction, QLabel, QVBoxLayout, QScrollArea
from threading import Thread
import requests
from bs4 import BeautifulSoup as bs

class MyWin(QWidget):
    def __init__(self):
        super(QWidget, self).__init__()

        self.vbox = QVBoxLayout()
        self.vbox.addStretch(1)

        data = ['https://ru.stackoverflow.com/',  
                'https://youtube.com', 
                'https://www.google.com/'
                ]

        for i in data:
            if i.startswith('http'):
                digit_label = QLabel(f'digit_label {i}')

                Thread(target=self.parse_func, args=(i, 'success', digit_label)).start()
                self.vbox.addWidget(digit_label)


        self.scrollarea = QScrollArea(self)
        self.scrollarea.resize(self.width(), self.height())      
        self.area = QWidget()
        self.area.setLayout(self.vbox)
        self.scrollarea.setWidget(self.area)

    def parse_func(self, url, string, label):
        page = requests.get(url)
        soup = bs(page.text, "html.parser")
        news = soup.find("title")
        news = str(news).replace('<title>', '')
        news = news.replace('</title>', '').lower()
        if news:
            label.setContextMenuPolicy(Qt.ActionsContextMenu)
            label.setText(news)
            show_action = QAction('Действие', self)
            show_action.triggered.connect(lambda c, url=url, label=label: self.foo(url, label))
            label.addAction(show_action)

    def foo(self, url, label):
        print(url)
        label.setText('success')


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = MyWin()
    w.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Попробуйте так:

import sys
from PyQt5 import QtWidgets,  QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QAction, QLabel, QVBoxLayout, QScrollArea
from threading import Thread
import requests
from bs4 import BeautifulSoup as bs


class Label(QLabel):                                                            # +++
    def __init__(self, text, parent=None):
        super(Label, self).__init__(parent) 

        self.url = ''
        self.news = ''
        self.setText(text)

        self.show_action = QAction('Действие', self) 
        self.show_action.triggered.connect(self.on_triggered)        
        self.addAction(self.show_action)  

    def params(self, url, news):
        self.url = url
        self.news = news

    def on_triggered(self):
        self.window().foo(self.url, self.news, self)


class MyWin(QWidget):
    def __init__(self):
        super(QWidget, self).__init__()

        self.vbox = QVBoxLayout()
        self.vbox.addStretch(1)

        data = ['https://ru.stackoverflow.com/',  
                'https://youtube.com', 
                'https://www.google.com/'
                ]
        for i in data:
            if i.startswith('http'):
                digit_label = Label(f'digit_label {i}')                        # - QLabel(f'digit_label {i}')
                Thread(target=self.parse_func, args=(i, 'success', digit_label)).start()
                self.vbox.addWidget(digit_label)
        self.vbox.addStretch(1)                                                # ++
        self.scrollarea = QScrollArea(self)
        self.scrollarea.resize(self.width(), self.height())      
        self.area = QWidget()
        self.area.resize(self.width(), self.height())                          # +++

        self.area.setLayout(self.vbox)
        self.scrollarea.setWidget(self.area)

    def parse_func(self, url, string, label):
        page = requests.get(url)
        soup = bs(page.text, "html.parser")
        news = soup.find("title")
        news = str(news).replace('<title>', '')
        news = news.replace('</title>', '').lower()
        if news:
            label.setContextMenuPolicy(Qt.ActionsContextMenu)
            label.setText(news)
            label.params(url, news)                                             # +++

    def foo(self, url, news, label):
        label.setText(f'<b>success:</b> {news}, {url}')


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = MyWin()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка