0

I recently switched to mac and my pyqt5 application isnt running like it should. I have a table set up with checkboxes in the rows. On a pc, when you click on a checkbox it first updates the row, then hits the checkbox. on mac it just hits the checkbox without triggering a row change. I'm cant even figure out what row i'm on to make any changes.

here is basic code that would work on a pc, but always outputs "0, 3" on a mac:

    for i in range(4):
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(i, item)
        item.setText(_translate("MainWindow", str(i)))

        self.tableWidget.setCellWidget(i, 0, QtWidgets.QCheckBox())
        self.tableWidget.cellWidget(i, 0).clicked.connect(lambda: print(self.tableWidget.currentRow(), i))

Here is the full file if you would like to test this yourself:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate

        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(195, 101, 371, 321))
        self.tableWidget.setObjectName("tableWidget")

        MainWindow.setCentralWidget(self.centralwidget)

        self.tableWidget.setColumnCount(1)
        self.tableWidget.setRowCount(4)

        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "Value"))

        for i in range(4):
            item = QtWidgets.QTableWidgetItem()
            self.tableWidget.setVerticalHeaderItem(i, item)
            item.setText(_translate("MainWindow", str(i)))

            self.tableWidget.setCellWidget(i, 0, QtWidgets.QCheckBox())
            self.tableWidget.cellWidget(i, 0).clicked.connect(lambda: print(self.tableWidget.currentRow(), i))


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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
Shaw
  • 169
  • 1
  • 3
  • 12
  • To your comment, I updated the post with a lot more information as I tackled the problem. This is a very clear version as before I had less information. I would appreciate any help you can give though. – Shaw Mar 30 '21 at 16:11
  • Ah ok, I thought it was dead. I'll keep that in mind for the future, thanks! So I take it you can't help? – Shaw Mar 30 '21 at 16:18
  • No no, this is a site for getting help with programing questions. Help with the question posted is not irrelevant. Flooding the comment section is though. – Shaw Mar 30 '21 at 16:24

1 Answers1

1

Not overly sure if this will be the solution, but be careful about connecting signals in a loop, as you may end up with the wrong variables being used (eg. i might always be 3).

Instead of creating the lambda like this:

lambda: print(self.tableWidget.currentRow(), i)

Try manually setting the i parameter:

lambda checked, i=i: print(self.tableWidget.currentRow(), i)

As pointed out by musicamante, clicked signals emit a checked variable, which will need to be ignored otherwise it will overwrite the value you've set for i.

As an alternative way of doing things, this is a potentially cleaner solution, but without testing I'm not sure if manually defining the slot as int will bypass the checked argument or not.

def setupUI(self):
    ...
    self.tableWidget.cellWidget(i, 0).clicked.connect(partial(self.someMethod, i))

@QtCore.Slot(int)
def someMethod(self, i):
    print(self.tableWidget.currentRow(), i)
Peter
  • 3,186
  • 3
  • 26
  • 59
  • No dice sadly, it always outputs "0, True" now. I changed it from i=i to x = i, and changed the i in the print to x, and it still printed "0, True". Thanks for the attempt! – Shaw Mar 30 '21 at 16:22
  • 1
    @Shaw `clicked` always has a `checked` argument (please, read the documentation...). Change to `lambda _, i=i: ...` – musicamante Mar 30 '21 at 16:39
  • 1
    Ah I wrote that without thinking assuming the code was already working, will update the answer :) – Peter Mar 30 '21 at 16:53
  • 1
    @musicamante and peter oh you lovely people thank you! This is perfect as is, but if you would be able to point me in the direction of the specific documentation so i know what to look for in the future, i would be much obliged. – Shaw Mar 30 '21 at 17:09
  • 1
    Start from https://doc.qt.io/qt-5.15/qtmodules.html and browse all classes (and those each class inherits). – musicamante Mar 30 '21 at 17:47
  • Just as a heads up, for this case in particular, I would search for [`QTableWidget`](https://doc.qt.io/qt-5/qtablewidget.html) and click on the first link for the docs. If what I needed wasn't in the signals, then I'd click the parent class. To find the `clicked` signal, you needed to go a few levels up to [`QAbstractItemView`](https://doc.qt.io/qt-5/qabstractitemview.html). – Peter Mar 30 '21 at 22:45