Search code examples
pythonpython-3.xpyqtpyqt5qtablewidget

Enable/Disable QPushButton upon row selection in QTableWidget


I have a QTableWidget and a Delete QPushButton.

I want the delete button to be enabled only when a row is selected from QTableWidget and if no row is selected then button should be disabled.

While initialization I am doing:

#Make rows selectable
self.tableWidget.setSelectionBehavior(QtWidgets.QTableWidget.SelectRows)
# Diable button initially
if not len(self.tableWidget.selectionModel().selectedRows()):
        self.btnDelete.setEnabled(False)

This sets Delete button to the disabled state.

How to I enable it on row selection?

Using: Python 3.8 , PyQt5 on Windows10

EDIT 1: Minimum working example:

import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout
from PyQt5.QtCore import pyqtSlot

class App(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'Fruits'
        self.left = 0
        self.top = 0
        self.width = 300
        self.height = 200
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.createTable()

        self.btndelete = QtWidgets.QPushButton("DELETE")
        self.btndelete.setObjectName("btndelete")
        self.btndelete.clicked.connect(self.deleteRow)
        if not len(self.tableWidget.selectionModel().selectedRows()):
            self.btndelete.setEnabled(False)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.tableWidget) 
        self.layout.addWidget(self.btndelete)

        self.setLayout(self.layout) 

        # Show widget
        self.show()

    def createTable(self):
       # Create table
        self.tableWidget = QTableWidget()
        self.tableWidget.setRowCount(4)
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setItem(0,0, QTableWidgetItem("Apple"))
        self.tableWidget.setItem(0,1, QTableWidgetItem("15"))
        self.tableWidget.setItem(1,0, QTableWidgetItem("Banana"))
        self.tableWidget.setItem(1,1, QTableWidgetItem("11"))
        self.tableWidget.setItem(2,0, QTableWidgetItem("Dogs"))
        self.tableWidget.setItem(2,1, QTableWidgetItem("10"))
        self.tableWidget.setItem(3,0, QTableWidgetItem("Cats"))
        self.tableWidget.setItem(3,1, QTableWidgetItem("2"))
        self.tableWidget.move(0,0)

        # table selection 
        self.tableWidget.setSelectionBehavior(QtWidgets.QTableWidget.SelectRows)

    def deleteRow(self):
        pass

    @pyqtSlot()
    def on_click(self):
        print("\n")
        for currentQTableWidgetItem in self.tableWidget.selectedItems():
            print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_()) 


Solution

  • You have to use the selectionChanged signal of the selectionModel associated to the QTableWidget to change the state of the button based on the number of rows selected:

        # ...
        self.tableWidget.setSelectionBehavior(QtWidgets.QTableWidget.SelectRows)
        self.tableWidget.selectionModel().selectionChanged.connect(
            self.on_selection_changed
        )
        self.on_selection_changed()
    
    def on_selection_changed(self):
        self.btnDelete.setEnabled(
            bool(self.tableWidget.selectionModel().selectedRows())
        )
    

    MWE:

    import sys
    from PyQt5.QtWidgets import (
        QApplication,
        QWidget,
        QTableWidget,
        QTableWidgetItem,
        QPushButton,
        QVBoxLayout,
    )
    from PyQt5.QtCore import pyqtSlot
    
    
    class App(QWidget):
        def __init__(self):
            super().__init__()
            self.title = "Fruits"
            self.left = 0
            self.top = 0
            self.width = 300
            self.height = 200
            self.initUI()
    
        def initUI(self):
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            self.createTable()
    
            self.btndelete = QPushButton("DELETE")
            self.btndelete.setObjectName("btndelete")
            self.btndelete.clicked.connect(self.deleteRow)
    
            self.on_selection_changed()
    
            lay = QVBoxLayout(self)
            lay.addWidget(self.tableWidget)
            lay.addWidget(self.btndelete)
    
            # Show widget
            self.show()
    
        def createTable(self):
            # Create table
            self.tableWidget = QTableWidget(4, 2)
            self.tableWidget.setItem(0, 0, QTableWidgetItem("Apple"))
            self.tableWidget.setItem(0, 1, QTableWidgetItem("15"))
            self.tableWidget.setItem(1, 0, QTableWidgetItem("Banana"))
            self.tableWidget.setItem(1, 1, QTableWidgetItem("11"))
            self.tableWidget.setItem(2, 0, QTableWidgetItem("Dogs"))
            self.tableWidget.setItem(2, 1, QTableWidgetItem("10"))
            self.tableWidget.setItem(3, 0, QTableWidgetItem("Cats"))
            self.tableWidget.setItem(3, 1, QTableWidgetItem("2"))
    
            # table selection
            self.tableWidget.setSelectionBehavior(QTableWidget.SelectRows)
            self.tableWidget.selectionModel().selectionChanged.connect(
                self.on_selection_changed
            )
    
        @pyqtSlot()
        def on_selection_changed(self):
            self.btndelete.setEnabled(
                bool(self.tableWidget.selectionModel().selectedRows())
            )
    
        def deleteRow(self):
            pass
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        ex = App()
        sys.exit(app.exec_())