Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Signal when QTableWidget scroll hits the end of the table?
Qt 6.11 is out! See what's new in the release blog

Signal when QTableWidget scroll hits the end of the table?

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 4 Posters 210 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DiBosco
    wrote last edited by
    #1

    I have a table with which I've populated some Mariadb results. When scrolling, as I go down the table I would like to trigger a search for the next set of results (rather than having all results being reported at once - with some large database tables you could end up with an unruly amount of data coming back for some queries!).

    It is possible to detect when the user scrolling makes the table hit the end? Both with the mouse scroll wheel and dragging the table down using he scroll bar?

    Thanks.

    JonBJ 1 Reply Last reply
    0
    • D DiBosco

      I have a table with which I've populated some Mariadb results. When scrolling, as I go down the table I would like to trigger a search for the next set of results (rather than having all results being reported at once - with some large database tables you could end up with an unruly amount of data coming back for some queries!).

      It is possible to detect when the user scrolling makes the table hit the end? Both with the mouse scroll wheel and dragging the table down using he scroll bar?

      Thanks.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote last edited by JonB
      #2

      @DiBosco
      Well, there is not actually anything "built in" for this. You have to roll something yourself.

      You can either intercept the scrollbar/mouse events, check for "reached or near the the bottom" and fetchMore() when it hits there. Or what some people do is have the rowCount() report more than the actual number of rows, so that technically you can scroll beyond the last row, and detect that and fetchMore() then. Variations on a theme.

      QTableWidget, as opposed to QTableView, may present some difficulties fiddling with its rowCount() as the model is built in and kind of hidden for subclassing. But in any case QTableWidget is quite the wrong widget for querying a SQL database like MariaDB, especially if a large number of rows/columns. Grossly inefficient. You should change to QTableView plus QSqlQueryModel or QSqlTableModel.

      as I go down the table I would like to trigger a search for the next set of results (rather than having all results being reported at once - with some large database tables you could end up with an unruly amount of data coming back for some queries!).

      Be aware that so long as you are using the QSql...Model... calls if there are a million matching rows it does not read all those million rows immediately! In fact, you should find that it (Qt) is hard-coded to fetch 256 rows at a time. The rest are still at the server while the query is active. You use void QSqlQueryModel::fetchMore() to fetch the next batch(es) of 256. This is more efficient than some sort of "issue a new query to pick up where you got to".

      jeremy_kJ 1 Reply Last reply
      1
      • D Offline
        D Offline
        DiBosco
        wrote last edited by DiBosco
        #3

        Hi Jon, thanks for that.

        Couple of points/follow-ups if I may.

        I wasn't aware of QSqlTableModel, QSqlQueryModel etc. I have been using QSqlQuery to carry out my mariadb query and putting results into a QStringList vector, then taking that data and putting it into a QTableWidget in the order I want it. It works beautifully and is really fast, even when I return, say, a thousand records with multiple columns.

        Are you basically saying this method is poor?

        I do have to be careful with insertRow, setRowCount,clearContents etc etc when using a QTableWidget, but as long as I careful it all works a treat.

        Now, the caveat as I said when you answered my DLL query a couple of weeks ago, I am strictly speaking an embedded software engineer, and although I am getting reasonably proficient in C++ and Qt, I am very happy to admit I am absolutely no expert, I might well be doing this in the wrong way. Or at least not the best way!

        1 Reply Last reply
        0
        • J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote last edited by
          #4

          @JonB suggestion is the better way to do it for sure, but for your current use case, simply listen to the valueChanged signal of your QScrollbar, something like:

          connect(ui->tableView->verticalScrollBar(), &QScrollBar::valueChanged,
                  this, &MyWidget::onScrollChanged);
          

          and than simply fetch more, when reaching the end, or near the ende, in case you want to start loading a little bit earlier for a smoother experience:

          void MyWidget::onScrollChanged(int value)
          {
              QScrollBar const * const bar = ui->tableView->verticalScrollBar();
              if (value >= bar->maximum() - 50) {
                  fetchNextPage();
              }
          }
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          JonBJ 1 Reply Last reply
          3
          • J.HilkJ J.Hilk

            @JonB suggestion is the better way to do it for sure, but for your current use case, simply listen to the valueChanged signal of your QScrollbar, something like:

            connect(ui->tableView->verticalScrollBar(), &QScrollBar::valueChanged,
                    this, &MyWidget::onScrollChanged);
            

            and than simply fetch more, when reaching the end, or near the ende, in case you want to start loading a little bit earlier for a smoother experience:

            void MyWidget::onScrollChanged(int value)
            {
                QScrollBar const * const bar = ui->tableView->verticalScrollBar();
                if (value >= bar->maximum() - 50) {
                    fetchNextPage();
                }
            }
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote last edited by
            #5

            @J.Hilk
            Ah, right, without subclassing. Do you get the QScrollBar::valueChanged() if it's from the wheel? You probably do, else you have to subclass to catch the wheel I believe.

            At the moment the OP is apparently using a QTableWidget, with its own standard item model data which has to be copied to etc. from some MariaDB SQL query. I advised they would be better off changing to QTableView + QSql...Model... calls to manage fetching chunks from the database better. Then they can use the fetchMore() rather than some new query to continue.

            1 Reply Last reply
            2
            • JonBJ JonB

              @DiBosco
              Well, there is not actually anything "built in" for this. You have to roll something yourself.

              You can either intercept the scrollbar/mouse events, check for "reached or near the the bottom" and fetchMore() when it hits there. Or what some people do is have the rowCount() report more than the actual number of rows, so that technically you can scroll beyond the last row, and detect that and fetchMore() then. Variations on a theme.

              QTableWidget, as opposed to QTableView, may present some difficulties fiddling with its rowCount() as the model is built in and kind of hidden for subclassing. But in any case QTableWidget is quite the wrong widget for querying a SQL database like MariaDB, especially if a large number of rows/columns. Grossly inefficient. You should change to QTableView plus QSqlQueryModel or QSqlTableModel.

              as I go down the table I would like to trigger a search for the next set of results (rather than having all results being reported at once - with some large database tables you could end up with an unruly amount of data coming back for some queries!).

              Be aware that so long as you are using the QSql...Model... calls if there are a million matching rows it does not read all those million rows immediately! In fact, you should find that it (Qt) is hard-coded to fetch 256 rows at a time. The rest are still at the server while the query is active. You use void QSqlQueryModel::fetchMore() to fetch the next batch(es) of 256. This is more efficient than some sort of "issue a new query to pick up where you got to".

              jeremy_kJ Offline
              jeremy_kJ Offline
              jeremy_k
              wrote last edited by
              #6

              @JonB said in Signal when QTableWidget scroll hits the end of the table?:

              @DiBosco
              Well, there is not actually anything "built in" for this. You have to roll something yourself.

              This is the purpose of QAbstractItemModel::canFetchMore(), coupled with fetchMore().

              qabstractitemview.cpp:

              void QAbstractItemView::verticalScrollbarValueChanged(int value)
              {
                  Q_D(QAbstractItemView);
                  if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
                      d->model->fetchMore(d->root);
              

              There's even an example: Fetch More Example

              Asking a question about code? http://eel.is/iso-c++/testcase/

              JonBJ 1 Reply Last reply
              2
              • jeremy_kJ jeremy_k

                @JonB said in Signal when QTableWidget scroll hits the end of the table?:

                @DiBosco
                Well, there is not actually anything "built in" for this. You have to roll something yourself.

                This is the purpose of QAbstractItemModel::canFetchMore(), coupled with fetchMore().

                qabstractitemview.cpp:

                void QAbstractItemView::verticalScrollbarValueChanged(int value)
                {
                    Q_D(QAbstractItemView);
                    if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root))
                        d->model->fetchMore(d->root);
                

                There's even an example: Fetch More Example

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote last edited by JonB
                #7

                @jeremy_k said in Signal when QTableWidget scroll hits the end of the table?:

                @DiBosco
                Well, there is not actually anything "built in" for this. You have to roll something yourself.

                This is the purpose of QAbstractItemModel::canFetchMore(), coupled with fetchMore().

                The "nothing actually built in" referred to no in-built facility to recognise a scroll to the bottom of a QTableWidget causing some kind of call to fetch more rows. I pointed the user at fetchMore() for the data, the bit he has to "roll" is the recognition of when to call it, such as your code.

                jeremy_kJ 1 Reply Last reply
                0
                • JonBJ JonB

                  @jeremy_k said in Signal when QTableWidget scroll hits the end of the table?:

                  @DiBosco
                  Well, there is not actually anything "built in" for this. You have to roll something yourself.

                  This is the purpose of QAbstractItemModel::canFetchMore(), coupled with fetchMore().

                  The "nothing actually built in" referred to no in-built facility to recognise a scroll to the bottom of a QTableWidget causing some kind of call to fetch more rows. I pointed the user at fetchMore() for the data, the bit he has to "roll" is the recognition of when to call it, such as your code.

                  jeremy_kJ Offline
                  jeremy_kJ Offline
                  jeremy_k
                  wrote last edited by
                  #8

                  @JonB said in Signal when QTableWidget scroll hits the end of the table?:

                  I pointed the user at fetchMore() for the data, the bit he has to "roll" is the recognition of when to call it, such as your code.

                  That's not my code. It's in the implementation of QAbstractItemView.

                  Asking a question about code? http://eel.is/iso-c++/testcase/

                  JonBJ 1 Reply Last reply
                  2
                  • jeremy_kJ jeremy_k

                    @JonB said in Signal when QTableWidget scroll hits the end of the table?:

                    I pointed the user at fetchMore() for the data, the bit he has to "roll" is the recognition of when to call it, such as your code.

                    That's not my code. It's in the implementation of QAbstractItemView.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote last edited by
                    #9

                    @jeremy_k Oh, wow, I'm sorry! I understand you now, it's already set to do that! Didn't know, thanks.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved