PyQt5 making dynamic widgets clickable and pass arguments to another function

限于喜欢 提交于 2019-12-24 08:44:10

问题


I am trying to make dynamic widgets and make them clickable. By clicking on one widget it should pass dynamic value to other widget. I have tried sender() and other options accessing the widget but nothing worked. All the widgets are sending information from the last widget.

Below is the code:

import sys
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QLabel, QMessageBox,QSizePolicy, QLayoutItem,QFrame,QHBoxLayout, QGridLayout, QVBoxLayout
from PyQt5.QtCore import QCoreApplication,QSize,QFileInfo
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from functools import partial
from PyQt5.QtCore import pyqtSlot
import sip 


class Screen(QWidget):
    def __init__(self):

        super(Screen, self).__init__()

        self.running_layout = QVBoxLayout()
        self.action_layout = QVBoxLayout()
        self.layout = QHBoxLayout(self)
        self.layout.addLayout(self.running_layout)
        self.layout.addLayout(self.action_layout)
        self.setLayout(self.layout)
        self.show()
        self.all_running()        
        self.actions_1('1')
    def buttonClicked(self):      
        sender = self.sender()
        print(sender + ' was pressed')

    def all_running(self):
        for i in range(5):
            button = QLabel("btn "+str(i))
            button.mouseReleaseEvent = lambda _ : self.actions_1(str(button.text()).split()[1])
            self.running_layout.addWidget(button)


        button2 = QLabel("btn 5")
        button2.mouseReleaseEvent = lambda _ : self.actions_1(str(button2.text()).split()[1])        
        self.running_layout.addWidget(button2)


    def actions_1(self,value):

        while not self.action_layout.isEmpty():
            print(self.action_layout.isEmpty())
            widget = self.action_layout.itemAt(0).widget()
            print("removing", widget)
            widget.setVisible(False)
            self.action_layout.removeWidget(widget)
            del widget
        self.action_layout = QVBoxLayout()
        self.layout.addLayout(self.action_layout)
        val = int(value)

        for i in range(val):
            actions_item = QLabel(str(i))
            self.action_layout.addWidget(actions_item)

app = QApplication(sys.argv)
Gui = Screen()
sys.exit(app.exec_())

Edited: I am trying to pass an int to actions based on the int value that number of widgets need to get populate. This int is based on the dynamic widget which i generated using the for loop. For example if the first widget of running_layout "btn 0" is clicked there won't be any widgets in the action_layout, If the second widget of running_layout "btn 1" is clicked there will be one widget "0" in the action_layout and so on based on the widget number. I am able to send the signal but on whichever dynamically created widget i click it is sending value 4 of last widget "btn 4" to the action_layout.


回答1:


To simplify the task we will create 2 widgets, the first one will be ClickableWidget that will have a signal indicating the number associated with the widget, whereas the second DynamicWidget will have a method that will be in charge of updating the number of widgets.

To know if an element is pressed we use the method installEventFilter() and eventFilter(), this filters the events giving information of the object and event, we will use setProperty("index", ) to store the number.

In the second widget I have implemented a method that is responsible for cleaning the widgets and creating some new widgets.

class ClickableWidget(QWidget):
    clicked = pyqtSignal(int)
    def  __init__(self, n=5, parent=None):
        QWidget.__init__(self, parent)
        self.hlayout = QVBoxLayout(self)
        for i in range(n):
            label = QLabel("btn {}".format(i), self)
            label.setProperty("index", i)
            self.hlayout.addWidget(label)
            label.installEventFilter(self)

    def eventFilter(self, obj, event):
        if isinstance(obj, QLabel) and event.type() == QEvent.MouseButtonPress:
            i = obj.property("index") 
            self.clicked.emit(i)
        return QWidget.eventFilter(self, obj, event)

class DynamicWidget(QWidget):
    def  __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.hlayout = QVBoxLayout(self)

    def changeWidget(self, n):
        def clearLayout(layout):
            item = layout.takeAt(0)
            while item:
                w = item.widget()
                if w:
                    w.deleteLater()
                lay = item.layout()
                if lay:
                    clearLayout(item.layout())
                item = layout.takeAt(0)

        clearLayout(self.hlayout)
        for i in range(n):
            label = QLabel("btn {}".format(i), self)
            self.hlayout.addWidget(label)


class Screen(QWidget):
    def __init__(self):
        super(Screen, self).__init__()
        self.layout = QHBoxLayout(self)
        c = ClickableWidget(6, self)
        d = DynamicWidget(self)
        c.clicked.connect(d.changeWidget)
        self.layout.addWidget(c)
        self.layout.addWidget(d)


来源:https://stackoverflow.com/questions/46696362/pyqt5-making-dynamic-widgets-clickable-and-pass-arguments-to-another-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!