PyQt5 使动态小部件可点击并将参数传递给另一个函数 [英] PyQt5 making dynamic widgets clickable and pass arguments to another function

查看:95
本文介绍了PyQt5 使动态小部件可点击并将参数传递给另一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作动态小部件并使它们可点击.通过单击一个小部件,它应该将动态值传递给其他小部件.我尝试过 sender() 和其他访问小部件的选项,但没有任何效果.所有小部件都从最后一个小部件发送信息.

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.

代码如下:

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_())

我正在尝试根据需要填充的小部件数量的 int 值将 int 传递给操作.这个 int 基于我使用 for 循环生成的动态小部件.例如,如果单击 running_layout "btn 0" 的第一个小部件,则 action_layout 中将没有任何小部件,如果单击 running_layout "btn 1" 的第二个小部件,则 action_layout 中将有一个小部件 "0" 等等基于小部件编号.我能够发送信号,但是在我单击哪个动态创建的小部件上,它会将最后一个小部件btn 4"的值 4 发送到 action_layout.

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.

推荐答案

为了简化任务,我们将创建 2 个小部件,第一个是 ClickableWidget,它将有一个信号指示与小部件,而第二个 DynamicWidget 将有一个方法负责更新小部件的数量.

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.

要知道某个元素是否被按下,我们使用方法 installEventFilter()eventFilter(),这将过滤提供对象和事件信息的事件,我们将使用 setProperty("index", ) 来存储数字.

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)

这篇关于PyQt5 使动态小部件可点击并将参数传递给另一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆