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

How to determine if cell of a QTableWidget is currently visible?



  • I've tried using the visualItemRect for a cell, but it is always valid even if a cell is not visible.
    Surely there is a way to tell if a cell is currently visible?

        QTableWidgetItem *item = mytable->item(row, column);
        QRect rect = mytable->visualItemRect (item);
        if (rect.isValid()) { /* always */ }


  • @Publicnamer It must be clear that not every cell is associated with a QTableWidgetItem, so my solution uses the concept of a cell and not a QTableWidgetItem. On the other hand I will assume that a cell is visible if at least a portion of it is visible. Considering the above, a possible solution is to use the headers to obtain the visualIndex and logicalIndex.

    #include <QApplication>
    #include <QHeaderView>
    #include <QTableWidget>
    #include <QTimer>
    #include <QVector>
    
    #include <QDebug>
    
    bool cellIsVisible(QTableWidget & tableWidget, int row, int column){
        if (tableWidget.rowCount() == 0 || tableWidget.columnCount() == 0)
            return false;
        if(row < 0 || row >= tableWidget.rowCount() || column < 0 || column >= tableWidget.columnCount())
            return false;
        QHeaderView *horizontal_header = tableWidget.horizontalHeader();
        QHeaderView *vertical_header = tableWidget.verticalHeader();
        int row_start = std::max(vertical_header->visualIndexAt(0), 0);
        int row_end = vertical_header->visualIndexAt(vertical_header->height());
        if(row_end == -1)
            row_end = tableWidget.rowCount() - 1;
        int column_start = std::max(horizontal_header->visualIndexAt(0), 0);
        int column_end = horizontal_header->visualIndexAt(horizontal_header->width());
        if(column_end == -1)
            column_end = tableWidget.columnCount() - 1;
        QVector<int> rows;
        for(int i=row_start; i <= row_end; i++){
            rows.push_back(vertical_header->logicalIndex(i));
        }
        QVector<int> columns;
        for(int j=column_start; j <= column_end; j++){
            columns.push_back(horizontal_header->logicalIndex(j));
        }
    
        return rows.contains(row) && columns.contains(column);
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QTableWidget tableWidget(10, 10);
        tableWidget.resize(640, 480);
        tableWidget.show();
    
        QTimer timer;
        timer.setInterval(500);
        QObject::connect(&timer, &QTimer::timeout, &tableWidget, [&tableWidget](){
            int row = 2;
            int column = 2;
            bool is_visible = cellIsVisible(tableWidget, row, column);
            qDebug() << row << column << is_visible;
        });
        timer.start();
    
        return a.exec();
    }
    


  • @eyllanesc That's certainly an interesting approach.

    I ended up coding it so that I ask the table what item is currently at the bottom of the table rectangle.
    I found that when I scroll to the bottom, I get a null pointer for that item. At all other times I get an item pointer.



  • @Publicnamer Your approach is suitable if the table did not apply the sorting or when you hide rows and columns. Your logic is similar to the visualIndex but that may be different from the internal position so I use the logicalIndex.



  • @eyllanesc I'm not using sorting as far as I know. I assume you mean sorting the contents automatically?



  • @Publicnamer Yes. I only point out the limitations of your solution for future readers. I am not saying that it is bad for you but I only warn the possible inconveniences for other users.


Log in to reply