Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Find what rows are visible in a scrolling table



  • I would appreciate if somebody can point me in the right direction. I have a table with 1 column and 60 rows of which 24 rows are visible at any one time. This table has 24 checkboxes on the side, one for each visible row. When a person clicks on the checkbox how can I find out which row was selected? If I can find out the top most row that is visible I can find out everything else. Is there any function that will tell me that say, 7th row is the top most visible row at this time? Thanks.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    No there's no such method. However you can use visualRect to achieve that.


  • Banned

    Disclaimer: This would have been posted much earlier but due to trolls on this forum I have to wait 600 seconds between posting helpful content so you can thank them for the major delays in getting help or no help since they never post answers just troll

    Why is the checkbox not associated directly with the row -- there is a checkable feature that can be set



  • SGaist: Thanks but I just started working with qt and visualRect is well beyond my grasp at this juncture.

    Denni: I took your advice and added the checkboxes into the table using the code from the answer section of this post:
    https://stackoverflow.com/questions/48057638/how-should-i-connect-checkbox-clicked-signals-in-table-widgets-in-pyqt5

    Now how do I center this checkbox in the table cell? Thanks.


  • Banned

    Well the easiest way would be to create a MUC (Minimal Usable Code) example and post that here demonstrating what you have then describe in as much detail as possible what you want to do -- the we can help you adjust your code to get what you are wanting



  • My code for inserting the checkbox in the table looks like this. The checkbox comes out as left-justified and I would like to center it. Thanks.

        for i in range(self.tableWidget.rowCount()):
            ch = QtWidgets.QCheckBox(parent=self.tableWidget)
            ch.clicked.connect(lambda checked, row=0, col=i: self.onStateChanged(checked, row, col))
            self.tableWidget.setCellWidget(i, 0, ch)

  • Banned

    Okay that is a code snippet not a MUC -- with a MUC I could copy/paste and run your code (aka its a complete USABLE example)

    The problems with snippets is you are at best going to get a snippet answer (aka incomplete) because the code the answer is based on is incomplete

    Still I will give it a look see and see what I can do with it



  • @ACollins said in Find what rows are visible in a scrolling table:

    ch.clicked.connect(lambda checked, row=0, col=i: self.onStateChanged(checked, row, col))

    Before you overlook it, I presume you intend:

    ch.clicked.connect(lambda checked, row=i, col=0: self.onStateChanged(checked, row, col))
    

    (row/col values swapped).

    This isn't the best way to do things [ I'm looking at you, @VRonin ;-) ], but from where you are now presumably you can always:

            w =  QtWidgets.QWidget(parent=self.tableWidget)
            w.setLayout(QtWidgets.QHBoxLayout())
            ch = QtWidgets.QCheckBox()
            w.layout().addWidget(ch)
            ch.clicked.connect(lambda checked, row=i, col=0: self.onStateChanged(checked, row, col))
            self.tableWidget.setCellWidget(i, 0, w)
    

    i.e. just put the checkbox in a horizontal layout.

    I'm not sure why in the code you copied from the author goes for a setCellWidget(QCheckBox) at all. Wouldn't a blank QTableWidgetItem with setFlags(... or Qt.ItemIsUserCheckable) suffice?


  • Banned

    Okay created a MUC (wish you had as that would have sped things up) also you ought not use Lambda expressions as they go back to the old school concept of stuffing as much as you can on a single line which because it is no longer necessary has been relegated to a do not use state if at all possible as it makes the line of code a bit more confusing and there is almost always a much clearer way to do it that adheres to proper coding practices. Of course I cannot tell what that would be because you do not show your target Slot so no way to know how to implement that correctly.

    Next there did not appear to be an easy way to make a checkbox centered within a column but on the flip-side you can make it appear centered by reducing the size of that column and that is what I do in this MUC also as I stated you do not need to add a QCheckBox to a QTableWidget as it already supports that as this MUC also demonstrates. If you have any more questions on this do ask them - more than happy to help you try to implement what you are trying to accomplish in the cleanest, clearest, and most concise method as possible. Remember quality code does just work correctly it is also very easily read by yourself and others as well as be self explanatory either because it is that simple or because comments were added.

    from PyQt5.QtCore    import Qt
    #from PyQt5.QtGui     import 
    from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
    from PyQt5.QtWidgets import QPushButton, QTableWidget, QHeaderView, QTableWidgetItem
    
    class TblWidg(QWidget):
        def __init__(self):
            QWidget.__init__(self)
            self.setWindowTitle('Checkable Table')
            Top=300; Left=300; Wdth=300; Hght=400
            self.setGeometry(Top, Left, Wdth, Hght)
    
            self.btnAdder = QPushButton('Add')
            self.btnAdder.clicked.connect(self.AddRows)
    
            HBox = QHBoxLayout()
            HBox.addStretch(1)
            HBox.addWidget(self.btnAdder)
    
            self.TblWdgt = QTableWidget()
            self.TblWdgt.setColumnCount(3)
          # Without this following line 39 is the Smallest a Column can be
            self.TblWdgt.horizontalHeader().setMinimumSectionSize(20)
    
            self.TblWdgt.setHorizontalHeaderLabels(['Description', ' ', 'Row'])
            self.TblWdgt.horizontalHeaderItem(0).setTextAlignment(Qt.AlignLeft)
          # This does not "center" it but it does make the column no wider than the checkbox
          # as this seemed to be the simplest solution to the proscribed issue      
            self.TblWdgt.setColumnWidth(1, 20)
            self.TblWdgt.horizontalHeaderItem(2).setTextAlignment(Qt.AlignCenter)
            self.TblWdgt.setColumnWidth(2, 40)
    
            HorzHedr = self.TblWdgt.horizontalHeader()
            HorzHedr.setSectionResizeMode(0, QHeaderView.Stretch)
            HorzHedr.setSectionResizeMode(1, QHeaderView.Fixed)
            HorzHedr.setSectionResizeMode(1, QHeaderView.Fixed)
    
            VBox = QVBoxLayout()
            VBox.addWidget(self.TblWdgt)
            VBox.addLayout(HBox)
            
            self.setLayout(VBox)
    
        def AddRows(self):
            for Cnt in range(10):
                Row = self.TblWdgt.rowCount()
                Text = 'Description-' + str(Cnt)
                self.TblWdgt.insertRow(Row)
    
                Col = 0
                DescItem = QTableWidgetItem(Text)
                self.TblWdgt.setItem(Row, Col, DescItem)
    
                Col = 1
                ChekItem = QTableWidgetItem()
                ChekItem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                ChekItem.setCheckState(Qt.Unchecked) 
                self.TblWdgt.setItem(Row, Col, ChekItem)
    
                Col = 2
                RowItem = QTableWidgetItem(str(Row))
                RowItem.setTextAlignment(Qt.AlignCenter)
                self.TblWdgt.setItem(Row, Col, RowItem)
    
    if __name__ == "__main__":
        MainEventHandler = QApplication([])
    
        MainApplication = TblWidg()
        MainApplication.show()
        
        MainEventHandler.exec()
    


  • Thank you very much JonB & Denni. All good and working perfectly!

    Denni: I wasn't sure what MUC is. I have been away from programming for 15+ years so this lingo is all new. I think I will read the FAQ.


Log in to reply