【问题标题】:How do you bind a dynamically created widget to a signal in PyQt?如何将动态创建的小部件绑定到 PyQt 中的信号?
【发布时间】:2013-07-12 18:46:30
【问题描述】:

我有一张表,里面装满了通过按下按钮创建的组合框。我的问题是你如何找出哪个组合框发生了变化?如果它是一个固定的组合框,我会使用以下内容:

QtCore.QObject.connect(self.comboBox, QtCore.SIGNAL(_fromUtf8("currentIndexChanged(int)")), self.dosomething)

为了更清楚,我添加了下面的示例代码:

from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(332, 122)
        Dialog.setMinimumSize(QtCore.QSize(332, 122))
        Dialog.setMaximumSize(QtCore.QSize(332, 122))
        self.tableWidget = QtGui.QTableWidget(Dialog)
        self.tableWidget.setGeometry(QtCore.QRect(10, 10, 256, 101))
        self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
        self.tableWidget.setColumnCount(2)   
        item = QtGui.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        self.tableWidget.setRowCount(0)
        self.layoutWidget_6 = QtGui.QWidget(Dialog)
        self.layoutWidget_6.setGeometry(QtCore.QRect(280, 30, 40, 54))
        self.layoutWidget_6.setObjectName(_fromUtf8("layoutWidget_6"))
        self.verticalLayout_2 = QtGui.QVBoxLayout(self.layoutWidget_6)
        self.verticalLayout_2.setMargin(0)
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.pushButton_2 = QtGui.QPushButton(self.layoutWidget_6)
        self.pushButton_2.setAutoDefault(False)
        self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
        self.verticalLayout_2.addWidget(self.pushButton_2)
        self.pushButton = QtGui.QPushButton(self.layoutWidget_6)
        self.pushButton.setAutoDefault(False)
        self.pushButton.setObjectName(_fromUtf8("pushButton"))
        self.verticalLayout_2.addWidget(self.pushButton)

        QtCore.QObject.connect(self.pushButton_2, QtCore.SIGNAL(_fromUtf8("clicked()")), self.add)

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton_2.setText(QtGui.QApplication.translate("Dialog", "+", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.setText(QtGui.QApplication.translate("Dialog", "-", None, QtGui.QApplication.UnicodeUTF8))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(QtGui.QApplication.translate("Dialog", "New Column", None, QtGui.QApplication.UnicodeUTF8))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(QtGui.QApplication.translate("Dialog", "New Column", None, QtGui.QApplication.UnicodeUTF8))

    def change(self):
        '''Depending on the comboBox whose index has changed,
         find the row and insert the right options in the comboBox
          in the next column'''

        #Find the row
        ins = self.tableWidget.focusWidget()
        selected_row = self.tableWidget.indexAt(ins.pos()).row()
        choice = self.tableWidget.cellWidget(0, selected_row).currentText()

        #Select the appropriate options
        if choice == 'B':
            choices_list = ['4', '5', '6']
        if choice == 'A':
            choices_list = ['1', '2', '3']

        #Set ComboBox in the next column
        comboBox = QtGui.QComboBox(self.tableWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        comboBox.setFont(font)

        for combo_ind, i in enumerate(choices_list):
            comboBox.addItem(_fromUtf8(""))
            comboBox.setItemText(combo_ind, QtGui.QApplication.translate("Dialog", i, None, QtGui.QApplication.UnicodeUTF8))

    def add(self):
        index = self.tableWidget.rowCount()
        self.tableWidget.insertRow(index)

        comboBox = QtGui.QComboBox(self.tableWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        comboBox.setFont(font)

        for combo_ind, i in enumerate(["A", "B"]):
            comboBox.addItem(_fromUtf8(""))
            comboBox.setItemText(combo_ind, QtGui.QApplication.translate("Dialog", i, None, QtGui.QApplication.UnicodeUTF8))     
        self.tableWidget.setCellWidget(index, 0, comboBox)

        comboBox = QtGui.QComboBox(self.tableWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        comboBox.setFont(font)

        #[1,2,3] is for A
        #[4,5,6] is for B
        for combo_ind, i in enumerate(['1', '2', '3']):
            comboBox.addItem(_fromUtf8(""))
            comboBox.setItemText(combo_ind, QtGui.QApplication.translate("Dialog", i, None, QtGui.QApplication.UnicodeUTF8))
        self.tableWidget.setCellWidget(index, 1, comboBox) 

app = QApplication(sys.argv)
app.setApplicationName('MyWindow')
window = QDialog()
ui = Ui_Dialog()
ui.setupUi(window)
window.show()
sys.exit(app.exec_())

【问题讨论】:

  • 在您的add 方法中,您创建了一个组合框,但我看不到您曾经将其任何信号连接到插槽。看起来你快到了,只需添加我们已经讨论过的QtCore.QObject.connect,添加一个方法(上面的dosomething)来处理事件,使用我在下面的答案中显示的 lambda 技巧,然后我认为你已经明白了。

标签: python user-interface pyqt


【解决方案1】:

您可能会尝试使用lambda,例如similar question

在您的情况下,它可能类似于以下内容:

QtCore.QObject.connect(self.comboBox, QtCore.SIGNAL("currentIndexChanged(int)"), lambda index: self.dosomething(combo_id, index))

您相应地更改您的self.dosomething 方法以采用额外的参数(例如,某种ID)。这将允许您传递有关该事件的一些识别信息,即它发生在哪个组合框,作为奖励,即使添加了新组件,您也可以对所有组件重复使用一种方法。

另请注意:在您的情况下,信号正在将值(int)传递给插槽。您也需要该信息,因此您将其捕获为 lambda 的参数(在上面我称之为 index )并将其与关于信号是哪个组合框的识别信息( combo_id )一起传递给您的插槽方法为了。

如果您的信号不向槽发送任何参数,例如单击按钮,则无需使用 lambda 参数,如下所示:

QtCore.QObject.connect(self.button, QtCore.SIGNAL("clicked()"), lambda: self.dosomething(button_id))

希望这会有所帮助。

【讨论】:

  • 那么,如何获得combo_id和索引呢?
  • index 是用户在你的组合框中设置的新索引(信号中传递的 int),它是为你设置的。 combo_id 是您在动态创建组合框时必须以某种方式设置的东西......您可以按照自己的方式进行操作,我只是以此为例。您可以在创建组合框并将其信号连接到插槽的同时执行此操作,就像您在上面所做的那样。有意义吗?
【解决方案2】:

您需要重新实现要动态创建的小部件。基本上this code 也是这个问题的答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    相关资源
    最近更新 更多