如何同步两个 QListWidgets 的滚动?
How to synchronize scrolling of the two QListWidgets?
有两个 QListWidget
项的数量相同。如何同步它们的滚动?
我的意思是当我滚动其中一个时,另一个应该得到相同的滚动。
你必须使用来自QListWidget
的verticalScrollBar()
的valueChanged()
信号,因为连接是双向的,它会导致使用[=14=为其执行不必要的任务]:
在下一节中,我将展示一个示例:
#include <QApplication>
#include <QListWidget>
#include <QHBoxLayout>
#include <QScrollBar>
class Widget: public QWidget{
Q_OBJECT
QListWidget w1;
QListWidget w2;
public:
Widget(QWidget *parent=Q_NULLPTR):QWidget(parent){
auto layout = new QHBoxLayout{this};
layout->addWidget(&w1);
layout->addWidget(&w2);
connect(w1.verticalScrollBar(), &QScrollBar::valueChanged, [this](int value){
w2.verticalScrollBar()->blockSignals(true);
w2.verticalScrollBar()->setValue(value);
w2.verticalScrollBar()->blockSignals(false);
});
connect(w2.verticalScrollBar(), &QScrollBar::valueChanged, [this](int value){
w1.verticalScrollBar()->blockSignals(true);
w1.verticalScrollBar()->setValue(value);
w1.verticalScrollBar()->blockSignals(false);
});
for(int i=0; i<100; i++){
w1.addItem(QString("item %1 of 1").arg(i));
w2.addItem(QString("item %1 of 2").arg(i));
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
假设您的 UI
中有两个 QListWidget
元素 listWidget_1
和 listWidget_2
,那么您可以使用 valueChanged
/setValue
signal/slot 对连接两个 listwidgets 的垂直滑块,事实上,我在这个 "two way" 连接中没有发现任何信号 re-bouncing 的问题,因为最终两个值将相同,我认为没有更多信号会被发射,因此你可以设置这样足够的连接:
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);
如果无论如何都应该阻止信号反弹,那么可以通过添加一个 slot
来调整模型来处理两个小部件的滚动并将它们都连接到该插槽:
connect(this->ui->listWidget_1->verticalScrollBar(),&QScrollBar::valueChanged
, this, &MainWindow::handleScroll);
connect(this->ui->listWidget_2->verticalScrollBar(),&QScrollBar::valueChanged
, this, &MainWindow::handleScroll);
插槽逻辑可以是:
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);
}
}
有两个 QListWidget
项的数量相同。如何同步它们的滚动?
我的意思是当我滚动其中一个时,另一个应该得到相同的滚动。
你必须使用来自QListWidget
的verticalScrollBar()
的valueChanged()
信号,因为连接是双向的,它会导致使用[=14=为其执行不必要的任务]:
在下一节中,我将展示一个示例:
#include <QApplication>
#include <QListWidget>
#include <QHBoxLayout>
#include <QScrollBar>
class Widget: public QWidget{
Q_OBJECT
QListWidget w1;
QListWidget w2;
public:
Widget(QWidget *parent=Q_NULLPTR):QWidget(parent){
auto layout = new QHBoxLayout{this};
layout->addWidget(&w1);
layout->addWidget(&w2);
connect(w1.verticalScrollBar(), &QScrollBar::valueChanged, [this](int value){
w2.verticalScrollBar()->blockSignals(true);
w2.verticalScrollBar()->setValue(value);
w2.verticalScrollBar()->blockSignals(false);
});
connect(w2.verticalScrollBar(), &QScrollBar::valueChanged, [this](int value){
w1.verticalScrollBar()->blockSignals(true);
w1.verticalScrollBar()->setValue(value);
w1.verticalScrollBar()->blockSignals(false);
});
for(int i=0; i<100; i++){
w1.addItem(QString("item %1 of 1").arg(i));
w2.addItem(QString("item %1 of 2").arg(i));
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
假设您的 UI
中有两个 QListWidget
元素 listWidget_1
和 listWidget_2
,那么您可以使用 valueChanged
/setValue
signal/slot 对连接两个 listwidgets 的垂直滑块,事实上,我在这个 "two way" 连接中没有发现任何信号 re-bouncing 的问题,因为最终两个值将相同,我认为没有更多信号会被发射,因此你可以设置这样足够的连接:
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);
如果无论如何都应该阻止信号反弹,那么可以通过添加一个 slot
来调整模型来处理两个小部件的滚动并将它们都连接到该插槽:
connect(this->ui->listWidget_1->verticalScrollBar(),&QScrollBar::valueChanged
, this, &MainWindow::handleScroll);
connect(this->ui->listWidget_2->verticalScrollBar(),&QScrollBar::valueChanged
, this, &MainWindow::handleScroll);
插槽逻辑可以是:
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);
}
}