Search code examples
pythonpyqtpyqt5qtablewidget

what is horizontalHeaderItem


I was following some examples to build QTableWidget with buttons inside cells and there was a suggestion to use QTableWidget.horizontalHeaderItem. Now, this works great but with it I am unable to get item back from specific row/column (as QTableWidget.horizontalHeaderItem do not have specified row).

But what is actual purpose of QTableWidget.horizontalHeaderItem and why would i use it instead of QTableWidget.item ?

Simple PyQT5 code:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.mainWidget = QtWidgets.QWidget()
        self.mytable = QtWidgets.QTableWidget(self.mainWidget)

        self.mytable.setColumnCount(1)
        self.mytable.setRowCount(2)

        self.my_edit_btn = QtWidgets.QPushButton('Edit')
        self.my_edit_btn.clicked.connect(self.button_A_pressed)
        self.mytable.setCellWidget(0, 0, self.my_edit_btn)
        item = QtWidgets.QTableWidgetItem()
        self.mytable.setHorizontalHeaderItem(0, item)
        self.mytable.horizontalHeaderItem(0).setText("Edit")
        # self.mytable.setItem(0, 0, item)
        # self.mytable.item(0, 0).setText("Edit")

        self.my_edit_btn = QtWidgets.QPushButton('Edit')
        self.my_edit_btn.clicked.connect(self.button_B_pressed)
        self.mytable.setCellWidget(1, 0, self.my_edit_btn)
        item = QtWidgets.QTableWidgetItem()
        self.mytable.setHorizontalHeaderItem(0, item)
        self.mytable.horizontalHeaderItem(0).setText("Edit")
        # self.mytable.setItem(1, 0, item)
        # self.mytable.item(1, 0).setText("Edit")

        self.verticalLayout.addWidget(self.mytable)
        MainWindow.setCentralWidget(self.centralwidget)

        item = self.mytable.item(0, 0)
        print(item)
        item = self.mytable.takeHorizontalHeaderItem(0)
        print(item)
        item = self.mytable.takeItem(0,0)
        print(item)

    def button_A_pressed(self):
        print("Button A")
        button = QtWidgets.qApp.focusWidget()
        print(button.pos())
        index = self.mytable.indexAt(button.pos())
        item = self.mytable.itemFromIndex(index)
        print(item)

    def button_B_pressed(self):
        print("Button B")
        button = QtWidgets.qApp.focusWidget()
        print(button.pos())
        index = self.mytable.indexAt(button.pos())
        item = self.mytable.itemFromIndex(index)
        print(item)

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

At the end I wanted to manually create QModelIndex based on specific row/column value. I found 'indexFromItem' method but i was unable to get specific item when using QTableWidget.horizontalHeaderItem.


Solution

  • If you remove the part of your logic where you use horizontalHeaderItem() and setHorizontalHeaderItem() your code keeps working, so using those elements never solved your problem. To verify this, replace the setupUi() method with the following code:

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
    
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.mainWidget = QtWidgets.QWidget()
        self.mytable = QtWidgets.QTableWidget(self.mainWidget)
    
        self.mytable.setColumnCount(1)
        self.mytable.setRowCount(2)
    
        self.my_edit_btn = QtWidgets.QPushButton('Edit')
        self.my_edit_btn.clicked.connect(self.button_A_pressed)
        self.mytable.setCellWidget(0, 0, self.my_edit_btn)
    
        self.my_edit_btn = QtWidgets.QPushButton('Edit')
        self.my_edit_btn.clicked.connect(self.button_B_pressed)
        self.mytable.setCellWidget(1, 0, self.my_edit_btn)
    
        self.verticalLayout.addWidget(self.mytable)
        MainWindow.setCentralWidget(self.centralwidget)
    

    what is horizontalHeaderItem?

    enter image description here

    A QTableWidgetItem is a class that allows you to modify the information of a QTableWidget in a simple way by abstracting what a QModelIndex and a model are. That is, it is a layer that allows us to interact with the model without knowing what the model is, that is also the idea of the QTableWidget.

    But what is actual purpose of QTableWidget.horizontalHeaderItem?

    In the case of the header it also contains information, for example if we want to establish a font, some text, etc. So also a QTableWidgetItem is associated to it that interacts with the method headerData() and setHeaderData() of the internal model. So in conclusion the setHorizontalHeaderItem method allows to establish a QTableWidgetItem that will have the information associated with the horizontal header.

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = QtWidgets.QTableWidget(10, 10)
        header_item = QtWidgets.QTableWidgetItem("Foo")
        font = QtGui.QFont("arial", 20)
        font.setBold(True)
        font.setItalic(True)
        header_item.setFont(font)
        w.setHorizontalHeaderItem(1, header_item)
        w.show()
        sys.exit(app.exec_())
    

    enter image description here

    Why would i use it instead of QTableWidget.item? As I pointed out to you, using horizontalHeaderItem was not your solution.