Search code examples
c++qtqt5qlistwidget

How to synchronize scrolling of the two QListWidgets?


There are two QListWidget with the same number of the items. How can synchronize their scrolling?

I mean when I scroll one of them, the other one should get same scrolling.


Solution

  • Suppose you have two QListWidget elements listWidget_1 and listWidget_2 in your UI, then you can use valueChanged/setValue signal/slot pair to connect vertical sliders of both listwidgets, indeed, I didn't find any issue of signals re-bouncing in this "two way" connection because eventually both values will be same and I think no more signals would be emitted, thus you can set such sufficient connections:

        connect(this->ui->listWidget_1->verticalScrollBar(), &QScrollBar::valueChanged,
    this->ui->listWidget_2->verticalScrollBar(), &QScrollBar::setValue);
        connect(this->ui->listWidget_2->verticalScrollBar(), &QScrollBar::valueChanged,
    this->ui->listWidget_1->verticalScrollBar(), &QScrollBar::setValue);
    // test lists:
        QList<QString> lw11, lw22;
        for (int x=0; x <200; x++){
            lw11.append("ListWidget1_" + QVariant(x).toString());
            lw22.append("The Other lw is at: " + QVariant(x).toString());
        }
        this->ui->listWidget_1->addItems(lw11);
        this->ui->listWidget_2->addItems(lw22);
    

    If signal rebounce should be blocked anyway, then the model can be adjusted by adding a single slot to handle scrolling for both widgets and connect both to that slot:

        connect(this->ui->listWidget_1->verticalScrollBar(),&QScrollBar::valueChanged
     , this, &MainWindow::handleScroll);
        connect(this->ui->listWidget_2->verticalScrollBar(),&QScrollBar::valueChanged
     , this, &MainWindow::handleScroll);
    

    and the slot logic can be :

    void MainWindow::handleScroll(int value)
    {
        // Logic for detecting sender() can be used ... but I don't see it's important
        // fast way to check which listWidget emitted the signal ...
        if (this->ui->listWidget_1->verticalScrollBar()->value() == value){
            qDebug() << "lw1 is in charge ...............";
            disconnect(this->ui->listWidget_2->verticalScrollBar(), &QScrollBar::valueChanged,this, &MainWindow::handleScroll); // prevent signal rebounce from the other lw
            this->ui->listWidget_2->verticalScrollBar()->setValue(value); 
            connect(this->ui->listWidget_2->verticalScrollBar(), &QScrollBar::valueChanged,this, &MainWindow::handleScroll);
    
        }else{
            qDebug() << "lw2 is in charge ...............";
            disconnect(this->ui->listWidget_1->verticalScrollBar(), &QScrollBar::valueChanged,this, &MainWindow::handleScroll);
            this->ui->listWidget_1->verticalScrollBar()->setValue(value);
            connect(this->ui->listWidget_1->verticalScrollBar(), &QScrollBar::valueChanged,this, &MainWindow::handleScroll);
        }
    }