【问题标题】:Passing parameters from programatically-built buttons从以编程方式构建的按钮传递参数
【发布时间】:2017-11-07 19:28:09
【问题描述】:

我正在尝试构建一个小的 PyQt5 应用程序,它将为我在文件目录上做一些工作。我需要构建一个 QGridLayout 来保存按钮。自然,内容可能会发生变化,所以我通过循环简单对象列表(路径、文件名等)来构建按钮。

我的问题是:当按钮的“on_click”操作是从循环构建时,我如何从按钮的“on_click”操作中传递识别参数?我不太关心点击返回的内容 - 我可以通过一种或另一种方式找到匹配的文件对象。

这是我的代码:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, \
    QGridLayout
from PyQt5.QtCore import pyqtSlot

from DirListing import Listing


class App(QDialog):
    def __init__(self):
        super().__init__()
        self.title = 'Grid Test'
        self.left = 10
        self.top = 10
        self.width = 320
        self.height = 500
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.createGridLayout()

        windowLayout = QVBoxLayout()
        windowLayout.addWidget(self.horizontalGroupBox)
        self.setLayout(windowLayout)

        self.show()

    def createGridLayout(self):
        self.horizontalGroupBox = QGroupBox("Grid")
        layout = QGridLayout()

        counter = 0

        for obj in Listing:

            button = QPushButton(obj.filename)
            button.clicked.connect(self.on_click)
            layout.addWidget(button, counter, 0)

            counter = counter + 1

        self.horizontalGroupBox.setLayout(layout)

    @pyqtSlot()
    def on_click(self):
        print("Halp!")

    def lower(self):
        if __name__ == '__main__':
            app = QApplication(sys.argv)
        ex = App()
        sys.exit(app.exec_())

有趣的部分只是以“for obj in Listing”开头的小循环——这是我的文件对象循环。我使用一个简单的计数器在 GridLayout 中为每个按钮向下移动一行。但我不知道如何将唯一参数从 click 函数中传递出去。

【问题讨论】:

  • 你能不能更好地解释一下,你想给on_click传递一个新参数吗?
  • 我想传递一个参数来标识链接到按钮的对象。按钮上的显示名称是文件名。我想要一个参数,上面写着“用户单击了名称为 的按钮”(或类似的名称。)然后我会知道要继续使用哪个文件对象。也许我把这弄得太复杂了。

标签: python python-3.x pyqt pyqt5


【解决方案1】:

有几种方法可以执行此任务,我将列出一些:

  1. 使用sender(),它是一个函数,它返回发出信号的对象和小部件的某些属性,在QPushButton 的情况下,您可以使用显示的文本

class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        for i in range(10):
            button = QPushButton("{}".format(i), self)
            self.layout().addWidget(button)
            button.clicked.connect(self.on_click)

    @pyqtSlot()
    def on_click(self):
        print("button-{}".format(self.sender().text()))
  1. 使用objectName(),其中每个小部件都有一个特定的名称

class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        for i in range(10):
            button = QPushButton("{}".format(i), self)
            self.layout().addWidget(button)
            button.setObjectName("button-{}".format(i))
            button.clicked.connect(self.on_click)

    @pyqtSlot()
    def on_click(self):
        print(self.sender().objectName())
  1. 使用 lambda 函数

class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        for i in range(10):
            button = QPushButton("{}".format(i), self)
            self.layout().addWidget(button)
            button.clicked.connect(lambda checked, i=i: self.on_click(i))

    def on_click(self, i):
        print("button-{}".format(i))
  1. 对于按钮,您可以使用QButtonGroup

class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        group = QButtonGroup(self)
        for i in range(10):
            button = QPushButton("{}".format(i), self)
            self.layout().addWidget(button)
            group.addButton(button, i)
        group.buttonClicked[int].connect(self.on_click)
        group.buttonClicked.connect(self.on_click2)

    @pyqtSlot(int)
    def on_click(self, i):
        print("button-{}".format(i))

    def on_click2(self, btn):
        print("2button-{}".format(btn.text()))
  1. 使用functools.partial

class Widget(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        for i in range(10):
            button = QPushButton("{}".format(i), self)
            self.layout().addWidget(button)
            import functools
            button.clicked.connect(functools.partial(self.on_click, i))

    @pyqtSlot()
    def on_click(self, i):
        print("button-{}".format(i))

【讨论】:

  • 请提供更多帮助...您能告诉我如何将您的代码插入到我的原始代码中吗?我的是从各种教程拼凑而成的。我仍在试图了解所有这些齿轮是如何组合在一起的。谢谢。
  • @Dito 给我分享一个可以执行的代码,你的看起来像伪代码,通过 github 或 gist,然后我会帮你做你想要的。
  • @Dito 还有你想要哪个选项?
  • 给我一点时间让它再次运行(我在测试时把它弄坏了)。我会按照你的要求发布所有内容。提前感谢您的帮助和耐心。我对哪种方法没有偏好。
  • @Dito 如果您学习对软件进行版本控制,您将始终拥有修改的备份,而 github 在这方面可以帮助您,我建议您尝试一下。当你有我可以执行的代码时通知我。 :P
猜你喜欢
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-28
  • 1970-01-01
  • 2013-04-03
  • 2012-08-01
相关资源
最近更新 更多