Search code examples
pythonpython-3.xpyqt5qtablewidget

how to get checked rows QtableWidget


I have this code. I want to delete any row whose tick was active when clicked the delete button

from main import Ui_MainWindow
from PyQt5 import QtWidgets
from  PyQt5.QtCore import Qt

def set_cell_elements(rows, l):
    ui.tableWidget.setRowCount(len(rows))
    ui.tableWidget.setVerticalHeaderLabels(rows)
    ui.tableWidget.verticalHeader().setDefaultAlignment(Qt.AlignVCenter)
    ui.tableWidget.horizontalHeader().setDefaultAlignment(Qt.AlignCenter)

    for r in range(0, len(l)):
        for i in range (0, len(l[r])) :
            text = l[r][i]
            ui.tableWidget.setItem(r, i, QtWidgets.QTableWidgetItem(str(text)))
            ui.tableWidget.item(r, i).setTextAlignment(Qt.AlignCenter)
            item = ui.tableWidget.item(r, 0)
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            item.setCheckState(Qt.Unchecked)
            item.checkState()
            table_ = ui.tableWidget.horizontalHeader()
            table_.setSectionResizeMode(i, QtWidgets.QHeaderView.ResizeToContents)

def delete_button():
    pass

import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
#=====================
rows = ['a', 'b', 'c', 'd', 'e', 'f']
l = [['Wade', 'Wade', 'Seth', 'Ivan', 'Riley'],
        ['Gilbert', 'Jorge', 'Dan', 'Brian', 'Roberto'],
        ['Ramon', 'Liam', 'Miles', 'Nathaniel', 'Lewis'],
        ['Ethan', 'Milton', 'Joshua', 'Claude', 'Glen'],
        ['Harvey', 'Blake', 'Antonio', 'Connor', 'Julian'],
        ['Aidan', 'Harold', 'Conner', 'Peter', 'Hunter']]

set_cell_elements(rows, l)
ui.delete_button.clicked.connect(delete_button)
MainWindow.show()
sys.exit(app.exec_())

I do not have a solution to get rows whose tick is active, can you help me !? Please


Solution

  • Welcome to StackOverflow! There are some missing information in your question to be able to help you with your problem. I can only guess the missing part of your code.

    I guess that you have used Qt Designer to create graphically your UI. I will suppose that you UI looks like that:

    Image representation of the guessed UI

    When compiled it gives:

    main.py

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'Ui_MainWindow.ui'
    #
    # Created by: PyQt5 UI code generator 5.15.4
    #
    # WARNING: Any manual changes made to this file will be lost when pyuic5 is
    # run again.  Do not edit this file unless you know what you are doing.
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(800, 600)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
            self.verticalLayoutWidget.setGeometry(QtCore.QRect(19, 16, 761, 521))
            self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
            self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
            self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetMaximumSize)
            self.verticalLayout.setContentsMargins(0, 0, 0, 0)
            self.verticalLayout.setObjectName("verticalLayout")
            self.delete_button = QtWidgets.QPushButton(self.verticalLayoutWidget)
            self.delete_button.setObjectName("delete_button")
            self.verticalLayout.addWidget(self.delete_button)
            self.verticalLayout_2 = QtWidgets.QVBoxLayout()
            self.verticalLayout_2.setObjectName("verticalLayout_2")
            self.tableWidget = QtWidgets.QTableWidget(self.verticalLayoutWidget)
            self.tableWidget.setBaseSize(QtCore.QSize(0, 0))
            self.tableWidget.setRowCount(6)
            self.tableWidget.setColumnCount(5)
            self.tableWidget.setObjectName("tableWidget")
            self.verticalLayout_2.addWidget(self.tableWidget)
            self.verticalLayout.addLayout(self.verticalLayout_2)
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 24))
            self.menubar.setObjectName("menubar")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
    
            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.delete_button.setText(_translate("MainWindow", "Delete selected rows"))
    

    The minimal changes solution would be:

    Solution 1.py

    from main import Ui_MainWindow
    from PyQt5 import QtWidgets
    from  PyQt5.QtCore import Qt
    
    def set_cell_elements(rows, l):
        ui.tableWidget.setRowCount(len(rows))
        ui.tableWidget.setVerticalHeaderLabels(rows)
        ui.tableWidget.verticalHeader().setDefaultAlignment(Qt.AlignVCenter)
        ui.tableWidget.horizontalHeader().setDefaultAlignment(Qt.AlignCenter)
    
        for r in range(0, len(l)):
            for i in range (0, len(l[r])) :
                text = l[r][i]
                ui.tableWidget.setItem(r, i, QtWidgets.QTableWidgetItem(str(text)))
                ui.tableWidget.item(r, i).setTextAlignment(Qt.AlignCenter)
                item = ui.tableWidget.item(r, 0)
                item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                item.setCheckState(Qt.Unchecked)
                item.checkState()
                table_ = ui.tableWidget.horizontalHeader()
                table_.setSectionResizeMode(i, QtWidgets.QHeaderView.ResizeToContents)
    
    def delete_button():
        for r in range(ui.tableWidget.rowCount(), 0, -1):
            item = ui.tableWidget.item(r - 1, 0)
            if item.checkState() == Qt.Checked:
                ui.tableWidget.removeRow(r - 1)
    
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    #=====================
    rows = ['a', 'b', 'c', 'd', 'e', 'f']
    l = [['Wade', 'Wade', 'Seth', 'Ivan', 'Riley'],
            ['Gilbert', 'Jorge', 'Dan', 'Brian', 'Roberto'],
            ['Ramon', 'Liam', 'Miles', 'Nathaniel', 'Lewis'],
            ['Ethan', 'Milton', 'Joshua', 'Claude', 'Glen'],
            ['Harvey', 'Blake', 'Antonio', 'Connor', 'Julian'],
            ['Aidan', 'Harold', 'Conner', 'Peter', 'Hunter']]
    
    set_cell_elements(rows, l)
    ui.delete_button.clicked.connect(delete_button)
    MainWindow.show()
    sys.exit(app.exec_())
    
    

    But there can be some more cleanup and simplification to your code:

    Solution 2.py

    from main import Ui_MainWindow
    from PyQt5 import QtWidgets
    
    from PyQt5.QtCore import Qt
    
    def set_cell_elements(row_headers, data_body):
        ui.tableWidget.setRowCount(len(row_headers))
        ui.tableWidget.setVerticalHeaderLabels(row_headers)
        ui.tableWidget.verticalHeader().setDefaultAlignment(Qt.AlignVCenter)
        ui.tableWidget.horizontalHeader().setDefaultAlignment(Qt.AlignCenter)
    
        for (row_number, current_row) in enumerate(data_body):
            for (column_number, current_text) in enumerate(current_row):
                ui.tableWidget.setItem(
                    row_number, column_number, 
                    QtWidgets.QTableWidgetItem(str(current_text))
                )
                ui.tableWidget.item(row_number, column_number).setTextAlignment(Qt.AlignCenter)
                row_header = ui.tableWidget.horizontalHeader()
                row_header.setSectionResizeMode(column_number, QtWidgets.QHeaderView.ResizeToContents)
            item = ui.tableWidget.item(row_number, 0)
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            item.setCheckState(Qt.Unchecked)
     
    def delete_button_action():    
        for current_row in range(ui.tableWidget.rowCount() - 1, -1, -1):
            first_item = ui.tableWidget.item(current_row, 0)
            state_current_row = first_item.checkState()
            if state_current_row == Qt.Checked:
                ui.tableWidget.removeRow(current_row)
        
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    
    row_headers = ('a', 'b', 'c', 'd', 'e', 'f')
    data_body = (
        ('Wade', 'Wade', 'Seth', 'Ivan', 'Riley'),
        ('Gilbert', 'Jorge', 'Dan', 'Brian', 'Roberto'),
        ('Ethan', 'Milton', 'Joshua', 'Claude', 'Glen'),
        ('Ramon', 'Liam', 'Miles', 'Nathaniel', 'Lewis'),
        ('Harvey', 'Blake', 'Antonio', 'Connor', 'Julian'),
        ('Aidan', 'Harold', 'Conner', 'Peter', 'Hunter')
    )
    
    set_cell_elements(row_headers, data_body)
    ui.delete_button.clicked.connect(delete_button_action)
    MainWindow.show()
    sys.exit(app.exec_())
    
    

    But you could code this in a more object-oriented way. That way, as long as you provide the containing widget and its initial data, you can plug it anywhere in your UI and it will take of itself:

    Solution 3.py

    import sys
    from main import Ui_MainWindow
    from PyQt5 import QtWidgets
    
    from PyQt5.QtCore import Qt
    
    class Simple_table_editor(Ui_MainWindow):
    
        def __init__(self, parent, row_headers, initial_data):
            super().__init__()
            self.setupUi(parent)
            self.tableWidget.setRowCount(len(row_headers))
            self.tableWidget.setVerticalHeaderLabels(row_headers)
            self.tableWidget.verticalHeader().setDefaultAlignment(Qt.AlignVCenter)
            self.tableWidget.horizontalHeader().setDefaultAlignment(Qt.AlignCenter)
    
            for (row_number, current_row) in enumerate(initial_data):
                for (column_number, current_text) in enumerate(current_row):
                    self.tableWidget.setItem(
                        row_number, column_number, 
                        QtWidgets.QTableWidgetItem(str(current_text))
                    )
                    self.tableWidget.item(row_number, column_number).setTextAlignment(Qt.AlignCenter)
                    row_header = self.tableWidget.horizontalHeader()
                    row_header.setSectionResizeMode(column_number, QtWidgets.QHeaderView.ResizeToContents)
                item = self.tableWidget.item(row_number, 0)
                item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                item.setCheckState(Qt.Unchecked)
            
            self.delete_button.clicked.connect(self.delete_button_action)
    
        def delete_button_action(self):    
            for current_row in range(self.tableWidget.rowCount() - 1, -1, -1):
                first_item = self.tableWidget.item(current_row, 0)
                state_current_row = first_item.checkState()
                if state_current_row == Qt.Checked:
                    self.tableWidget.removeRow(current_row)
    
    row_headers = ('a', 'b', 'c', 'd', 'e', 'f')
    data_body = (
        ('Wade', 'Wade', 'Seth', 'Ivan', 'Riley'),
        ('Gilbert', 'Jorge', 'Dan', 'Brian', 'Roberto'),
        ('Ethan', 'Milton', 'Joshua', 'Claude', 'Glen'),
        ('Ramon', 'Liam', 'Miles', 'Nathaniel', 'Lewis'),
        ('Harvey', 'Blake', 'Antonio', 'Connor', 'Julian'),
        ('Aidan', 'Harold', 'Conner', 'Peter', 'Hunter')
    )
    
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    table_editor = Simple_table_editor(MainWindow, row_headers, data_body)
    MainWindow.show()
    sys.exit(app.exec_())
    

    If my guesses are wrong and you meant to do something else, please give us more detail.