How can i align a CellWidget of a TableWidget to the center of the Item in pyqt5

Viewed 298

i have a comboBox inside of a tableWidget and the verticalHeader DefaultSectionSize is 60.

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self,parent)
        self.table = QTableWidget()
        self.setCentralWidget(self.table)
       
        self.table.verticalHeader().setDefaultSectionSize(60)
        self.table.setColumnCount(2)
        self.table.setRowCount(2)
        
        data = ["1","2"]
    
        for i in range(2):
            item = QTableWidgetItem(data[i])
            self.table.setItem(i,0,item)
            self.combo_sell = QComboBox()
            self.combo_sell.setMaximumHeight(30)
            self.table.setCellWidget(i,1,self.combo_sell)

But since i set the maximum size of the comboBox to 30, it stays in the top of the item.

image

I want to know if there's a way to align it to the center.

1 Answers

When setting an index widget, the view tries to set the widget geometry based on the visualRect() of the index. Setting a fixed dimension forces the widget to align itself to the default origin, which is usually the top left corner.

The only way to vertically center a widget with a fixed height is to use a container with a vertical box layout and add the combo to it:

        for i in range(2):
            item = QTableWidgetItem(data[i])
            item.setTextAlignment(Qt.AlignCenter)
            self.table.setItem(i,0,item)
            container = QWidget()
            layout = QVBoxLayout(container)
            combo_sell = QComboBox()
            layout.addWidget(combo_sell)
            combo_sell.setMaximumHeight(30)
            self.table.setCellWidget(i, 1, container)

Note: setting instance attributes in a for loop is pointless, as the reference is lost every time the cycle loops.

If you need a simple reference to the combo, you can set it as an attribute of the widget:

    container.combo_sell = QComboBox()

In this way you can easily access it when required:

        widget = self.table.cellWidget(row, column)
        if widget and hasattr(widget, 'combo'):
            combo = widget.combo
            print(combo.currentIndex())

Note that the reference is created for the python wrapper of the widget, and that behavior might change in future versions of Qt. A better and safer way to achieve this would be to use a subclass, which would also allow easier access to the combo:

class TableCombo(QWidget):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout(self)
        self.combo = QComboBox()
        layout.addWidget(self.combo)
        self.combo.setMaximumHeight(30)
        self.currentIndex = self.combo.currentIndex
        self.setCurrentIndex = self.combo.setCurrentIndex
        self.addItems = self.combo.addItems

# ...

            combo_sell = TableCombo()
            self.table.setCellWidget(i, 1, combo_sell)

# ...

        combo = self.table.cellWidget(row, column)
        print(combo.currentIndex())
Related