Problems with QTableView::scrollToBottom() and different verticalHeader section sizes



  • Hello,

    I want to achieve a "tail" mode using QTableView: Each time a new row is inserted into the model and displayed in the view, I want to scroll the view down to display the newest row at the bottom of the view.

    This does almost work, the only problem is that the newest row in the view is not always aligned with the bottom of the view.

    The implementation at the moment is as follows:
    The QTableView has to display rows that can differ in their row height (verticalHeaderSize). That is because the data for the cell is text that can consist of multiple lines.

    I have a QStandardItemModel that contains the data. As soon as the model receives a new row, I call verticalHeader()->resizeRowToContents(row) to expand that row. Directly after that I call QTableView::scrollToBottom() and expect the QTableView to scroll down to the bottom.

    This does not work like expected. I think that one of the causes is that directly after resizing the verticalHeaderSection the QScrollBar::maximum() is not yet updated. So when I call scrollToBottom() the QTableView "thinks" it is already at the bottom.

    Do you have any hints on how I can get this working?

    Find attached a stripped down example that illustrates the issue.

    Thanks for your help!
    Markus

    @#include <QtGui>
    #include <QtCore>

    class LineProducer : public QThread {
    Q_OBJECT
    public:
    LineProducer()
    : m_maxRows(5000)
    {

    }
    
    void run()
    {
        QTime now = QTime::currentTime();
        qsrand(now.msec());
        for (int row = 0; row <= m_maxRows; row++) {
            int lineBreaks =  (qrand() % (int)(10)) +1;
            QStringList lines;
            for (int cnt=0;cnt<lineBreaks;cnt++) {
                lines << "foooooobar ooooommmmmoooooo";
            }
            QString currentRow = lines.join("\n");
            emit lineCreated(currentRow);
            sleep(1);
        }
    }
    

    private:
    int m_maxRows;

    signals:
    void lineCreated(const QString& line);
    };

    class LineConsumer : public QObject{
    Q_OBJECT
    public:
    LineConsumer()
    : m_model(new QStandardItemModel),
    m_view(new QTableView)
    {
    m_view->resize(640,480);
    m_view->setModel(m_model);

        m_view->horizontalHeader()->setDefaultSectionSize(200);
        m_view->horizontalHeader()->setStretchLastSection(true);
    
        connect(m_model,SIGNAL(rowsInserted(QModelIndex,int,int)),this,SLOT(resizeRow(QModelIndex,int,int)));
    
    }
    

    public slots:
    void lineReceived(const QString& line)
    {
    m_model->appendRow(new QStandardItem(line));
    }

    public:
    QStandardItemModel* model()
    {
    return m_model;
    }

    void show()
    {
        m_view->show();
    }
    

    public slots:
    void resizeRow(QModelIndex,int startRow,int endRow)
    {
    m_view->resizeRowToContents(startRow);
    m_view->scrollToBottom();
    }

    private:
    QStandardItemModel* m_model;
    QTableView* m_view;

    };

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    LineProducer p;
    LineConsumer c;
    
    QObject::connect(&p,SIGNAL(lineCreated(QString)),&c,SLOT(lineReceived(QString)));
    c.show();
    p.start();
    
    return a.exec&#40;&#41;;
    

    }

    #include "main.moc"
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.