pythonpyqtpyqt5pysidepyside6

How do you change the position (column and row) of a PyQt QWidget inside a QTableWidget?


I want to move a QWidget from one position to another. I tried the following:

import sys
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QTableWidget, QLabel, QPushButton, QVBoxLayout, QWidget
)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.table = QTableWidget(5, 2)  # 5 rows, 2 columns
        self.table.setHorizontalHeaderLabels(["Column 1", "Column 2"])

        # Add a QLabel to cell (4, 0)
        label = QLabel("Test")
        self.table.setCellWidget(4, 0, label)

        # Add a button to trigger the move
        self.button = QPushButton("Move widget")
        self.button.clicked.connect(self.move_widget)

        layout = QVBoxLayout()
        layout.addWidget(self.table)
        layout.addWidget(self.button)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def move_widget(self):
        """Move the widget from cell (4,0) to (3,0)."""
        widget = self.table.cellWidget(4, 0)

        self.table.removeCellWidget(4, 0)
        self.table.setCellWidget(3, 0, widget)
        widget.show()

        # Debug: Verify the move
        print(f"Cell (3,0) now has: {self.table.cellWidget(3, 0)}")
        print(f"Cell (4,0) now has: {self.table.cellWidget(4, 0)}")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

This has the following output:

Cell (3,0) now has: <PySide6.QtWidgets.QLabel(0x26d65f7fc00) at 0x0000026D67071380>
Cell (4,0) now has: None

Process finished with exit code -1073741819 (0xC0000005)

It seems to me that upon rendering, the QLabel is removed. Is there any way to prevent this from happening?


Solution

  • Using @musicamante's explanation I got my code to work. It is a bit of a workaround, but it works. Here is the fixed code:

    import sys
    from PySide6.QtWidgets import (
        QApplication, QMainWindow, QTableWidget, QLabel, QPushButton, QVBoxLayout, QWidget, QHBoxLayout
    )
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.table = QTableWidget(5, 2)  # 5 rows, 2 columns
            self.table.setHorizontalHeaderLabels(["Column 1", "Column 2"])
    
            # Add a QLabel to cell (4, 0)
            label_container = QWidget()
            widget_layout = QHBoxLayout(label_container)
    
            self.label = QLabel("Test", label_container)
            widget_layout.addWidget(self.label)
            self.table.setCellWidget(4, 0, label_container)
    
            # Add a button to trigger the move
            self.button = QPushButton("Move widget")
            self.button.clicked.connect(self.move_widget)
    
            layout = QVBoxLayout()
            layout.addWidget(self.table)
            layout.addWidget(self.button)
    
            container = QWidget()
            container.setLayout(layout)
            self.setCentralWidget(container)
    
        def move_widget(self):
            """Move the widget from cell (4,0) to (3,0)."""
            new_container = QWidget()
            widget_layout = QHBoxLayout(new_container)
            widget_layout.addWidget(self.label)
    
            self.table.setCellWidget(3, 0, new_container)
            self.table.removeCellWidget(4, 0)
    
            # Debug: Verify the move
            print(f"Cell (3,0) now has: {self.table.cellWidget(3, 0)}")
            print(f"Cell (4,0) now has: {self.table.cellWidget(4, 0)}")
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec())
    

    It uses a layout as well so that the QLabel is centred, this is probably not necessary for other widgets.