vendredi 24 août 2018

How do you send the row of a checkbox to a slot in a column of checkboxes in a QTableWidget (PyQt4)?

This is what I have now. When any checkbox is clicked, self.checkbox_change get executed but the row and checkbox parameters is always that of the last checkbox. I got the slots example from QCheckBox state change PyQt4 but it seems there might be an issue with the lambda x: slot() or slot = partial() functions.

Essentially what I am trying to accomplish is to update multiple checkboxes based on metadata item.setData(Qt.UserRole, QVariant(QString(record[0]))) stored in the same row. The plan is to update all the checkboxes on any checkbox change.

#!/usr/bin/env python

from functools import partial
import sys

from PyQt4.QtCore import *
from PyQt4.QtGui import *

import ui_mainwindow


class MainWindow(QMainWindow, ui_mainwindow.Ui_MainWindow):
    def __init__(self, parent):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.contacts = [
            ('test1', 'Test1'),
            ('test2', 'Test2'),
            ('test3', 'Test3'),
            ('test4', 'Test4'),
            ('test5', 'Test5'),
            ('test6', 'Test6'),
        ]
        self.init_tablewidget()

    def init_tablewidget(self):
        self.tableWidget.clear()
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(10)
        self.tableWidget.setColumnWidth(0, 100)
        self.tableWidget.setColumnWidth(1, 60)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tableWidget.setCornerButtonEnabled(False)
        self.checkboxes = []

        for row, record in enumerate(self.contacts):
            item = QTableWidgetItem(record[1])
            item.setData(Qt.UserRole, QVariant(QString(record[0])))
            item.setTextAlignment(Qt.AlignLeft)
            item.setFlags(Qt.ItemIsEnabled)
            self.tableWidget.setItem(row, 0, item)

            widget = QWidget()
            checkbox = QCheckBox()
            checkbox.setCheckState(Qt.Checked)
            self.checkboxes.append(checkbox)
            layout = QHBoxLayout(widget)
            layout.addWidget(checkbox)
            layout.setAlignment(Qt.AlignCenter)
            layout.setContentsMargins(0, 0, 0, 0)
            widget.setLayout(layout)
            self.tableWidget.setCellWidget(row, 1, widget)

            # Got the slot connection code from:
            # https://stackoverflow.com/questions/38437347/qcheckbox-state-change-pyqt4

            slot = partial(self.checkbox_change, checkbox, row)
            checkbox.stateChanged.connect(lambda x: slot())

        horizontalHeader = self.tableWidget.horizontalHeader()
        horizontalHeader.setStretchLastSection(True)

        item = QTableWidgetItem('Company')
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem('Send')
        self.tableWidget.setHorizontalHeaderItem(1, item)

    def checkbox_change(self, checkbox, row):
        print 'change', id(checkbox), row


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle(QStyleFactory.create('vista'))
    form = MainWindow(None)
    form.showNormal()
    sys.exit(app.exec_())

Here is the designer generated ui_mainwindow.py file:

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(789, 694)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.tableWidget = QtGui.QTableWidget(self.centralwidget)
        self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.verticalLayout.addWidget(self.tableWidget)
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.sendPushButton = QtGui.QPushButton(self.centralwidget)
        self.sendPushButton.setObjectName(_fromUtf8("sendPushButton"))
        self.horizontalLayout.addWidget(self.sendPushButton)
        self.quitPushButton = QtGui.QPushButton(self.centralwidget)
        self.quitPushButton.setObjectName(_fromUtf8("quitPushButton"))
        self.horizontalLayout.addWidget(self.quitPushButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 789, 25))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuFile = QtGui.QMenu(self.menubar)
        self.menuFile.setObjectName(_fromUtf8("menuFile"))
        MainWindow.setMenuBar(self.menubar)
        self.action_Exit = QtGui.QAction(MainWindow)
        self.action_Exit.setObjectName(_fromUtf8("action_Exit"))
        self.menuFile.addAction(self.action_Exit)
        self.menubar.addAction(self.menuFile.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QObject.connect(self.quitPushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), MainWindow.close)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        MainWindow.setTabOrder(self.tableWidget, self.sendPushButton)
        MainWindow.setTabOrder(self.sendPushButton, self.quitPushButton)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.sendPushButton.setText(_translate("MainWindow", "Send Emails", None))
        self.quitPushButton.setText(_translate("MainWindow", "Quit", None))
        self.menuFile.setTitle(_translate("MainWindow", "&File", None))
        self.action_Exit.setText(_translate("MainWindow", "E&xit", None))
        self.action_Exit.setShortcut(_translate("MainWindow", "Ctrl+Q", None))




Aucun commentaire:

Enregistrer un commentaire