Qt:多个 QListWidgets 并且只选择了一个条目
Qt: Multiple QListWidgets and only a single entry selected
我有几个 QListWidget
并且只允许对所有这些列表的一行进行 select 编辑。因此,例如,如果我 select 列表之一中的一行,其他列表中的任何其他 selection 将被清除。我怎样才能做到这一点?
是否有内置的方法来执行此操作(类似于按钮的 QButtonGroup)?如果没有,您会建议我在尝试自己实施时采用什么方法?
感谢您的帮助和亲切的问候,
托德
据我所知,没有现成的内置功能可以在多个列表视图中提供单一选择。
相反,它可以由 QSelectionModel::selectionChanged
信号的相应信号处理程序完成,只要所涉及的列表视图之一的选择发生变化,它就会执行此操作。
因此,您必须考虑清除选择也会发出 selectionChanged
信号。 (否则,您可能最终会递归调用信号处理程序,直到发生 堆栈溢出。)
不幸的是,我在 C++ 中使用 Qt。 (我的 Python 知识相当有限。)
因此,我现在所能提供的只是我在 C++ 中的“概念证明”:
#include <QtWidgets>
void singleSel(QListView *pLstView, const QList<QListView*> &pLstViews)
{
for (QListView *pLstViewI : pLstViews) {
if (pLstViewI == pLstView) continue; // skip sender
// the check is necessary to prevent recursions...
if (pLstView->selectionModel()->hasSelection()) {
// ...as this causes emission of selectionChanged() signal as well:
pLstViewI->selectionModel()->clearSelection();
}
}
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version: " << QT_VERSION_STR;
QApplication app(argc, argv);
// build contents
QStandardItemModel tblModel(0, 1);
for (int i = 0; i < 10; ++i) {
tblModel.appendRow(
new QStandardItem(QString::fromUtf8("Entry %0").arg(i + 1)));
}
// build some GUI
QWidget win;
QHBoxLayout qHBox;
QListView lstView1;
lstView1.setModel(&tblModel);
qHBox.addWidget(&lstView1);
QListView lstView2;
lstView2.setModel(&tblModel);
qHBox.addWidget(&lstView2);
QListView lstView3;
lstView3.setModel(&tblModel);
qHBox.addWidget(&lstView3);
win.setLayout(&qHBox);
win.show();
// install signal handlers
QList<QListView*> pLstViews = { &lstView1, &lstView2, &lstView3 };
QObject::connect(lstView1.selectionModel(),
&QItemSelectionModel::selectionChanged,
[&lstView1, &pLstViews](const QItemSelection&, const QItemSelection &)
{
singleSel(&lstView1, pLstViews);
});
QObject::connect(lstView2.selectionModel(),
&QItemSelectionModel::selectionChanged,
[&lstView2, &pLstViews](const QItemSelection&, const QItemSelection &)
{
singleSel(&lstView2, pLstViews);
});
QObject::connect(lstView3.selectionModel(),
&QItemSelectionModel::selectionChanged,
[&lstView3, &pLstViews](const QItemSelection&, const QItemSelection &)
{
singleSel(&lstView3, pLstViews);
});
// exec. application
return app.exec();
}
我在 Windows 10(64 位)上编译和测试。这是它的样子:
更新:
我尝试将 C++ 应用程序移植到 Python/PyQt5:
#!/usr/bin/python3
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QListView
from PyQt5.QtGui import QStandardItemModel, QStandardItem
def singleSelect(lstView, lstViews):
for lstViewI in lstViews:
if lstViewI == lstView:
continue
# the check is necessary to prevent recursions...
if lstViewI.selectionModel().hasSelection():
# ...as this causes emission of selectionChanged() signal as well:
lstViewI.selectionModel().clearSelection()
if __name__ == '__main__':
app = QApplication(sys.argv)
# build contents
tblModel = QStandardItemModel(0, 1)
for i in range(0, 10):
tblModel.appendRow(QStandardItem("Entry %d" % (i + 1)))
# build GUI
win = QWidget()
hBox = QHBoxLayout()
lstView1 = QListView()
lstView1.setSelectionMode(QListView.SingleSelection)
lstView1.setModel(tblModel)
hBox.addWidget(lstView1)
lstView2 = QListView()
lstView2.setSelectionMode(QListView.SingleSelection)
lstView2.setModel(tblModel)
hBox.addWidget(lstView2)
lstView3 = QListView()
lstView3.setSelectionMode(QListView.SingleSelection)
lstView3.setModel(tblModel)
hBox.addWidget(lstView3)
win.setLayout(hBox)
win.show()
# install signal handlers
lstViews = [lstView1, lstView2, lstView3]
lstView1.selectionModel().selectionChanged.connect(lambda sel, unsel: singleSelect(lstView1, lstViews))
lstView2.selectionModel().selectionChanged.connect(lambda sel, unsel: singleSelect(lstView2, lstViews))
lstView3.selectionModel().selectionChanged.connect(lambda sel, unsel: singleSelect(lstView3, lstViews))
# exec. application
sys.exit(app.exec_())
从我在测试中看到的情况来看,它的行为与用 C++ 编写的类似。
唯一的例外是我在更改列表视图时必须在条目上单击两次。
正如我已经说过的:我在 PyQt 方面的经验非常有限。 (实际上,我今天是从制作这个样本开始的。)因此,我可能已经监督了一些事情。请对它持保留态度...
我有几个 QListWidget
并且只允许对所有这些列表的一行进行 select 编辑。因此,例如,如果我 select 列表之一中的一行,其他列表中的任何其他 selection 将被清除。我怎样才能做到这一点?
是否有内置的方法来执行此操作(类似于按钮的 QButtonGroup)?如果没有,您会建议我在尝试自己实施时采用什么方法?
感谢您的帮助和亲切的问候, 托德
据我所知,没有现成的内置功能可以在多个列表视图中提供单一选择。
相反,它可以由 QSelectionModel::selectionChanged
信号的相应信号处理程序完成,只要所涉及的列表视图之一的选择发生变化,它就会执行此操作。
因此,您必须考虑清除选择也会发出 selectionChanged
信号。 (否则,您可能最终会递归调用信号处理程序,直到发生 堆栈溢出。)
不幸的是,我在 C++ 中使用 Qt。 (我的 Python 知识相当有限。)
因此,我现在所能提供的只是我在 C++ 中的“概念证明”:
#include <QtWidgets>
void singleSel(QListView *pLstView, const QList<QListView*> &pLstViews)
{
for (QListView *pLstViewI : pLstViews) {
if (pLstViewI == pLstView) continue; // skip sender
// the check is necessary to prevent recursions...
if (pLstView->selectionModel()->hasSelection()) {
// ...as this causes emission of selectionChanged() signal as well:
pLstViewI->selectionModel()->clearSelection();
}
}
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version: " << QT_VERSION_STR;
QApplication app(argc, argv);
// build contents
QStandardItemModel tblModel(0, 1);
for (int i = 0; i < 10; ++i) {
tblModel.appendRow(
new QStandardItem(QString::fromUtf8("Entry %0").arg(i + 1)));
}
// build some GUI
QWidget win;
QHBoxLayout qHBox;
QListView lstView1;
lstView1.setModel(&tblModel);
qHBox.addWidget(&lstView1);
QListView lstView2;
lstView2.setModel(&tblModel);
qHBox.addWidget(&lstView2);
QListView lstView3;
lstView3.setModel(&tblModel);
qHBox.addWidget(&lstView3);
win.setLayout(&qHBox);
win.show();
// install signal handlers
QList<QListView*> pLstViews = { &lstView1, &lstView2, &lstView3 };
QObject::connect(lstView1.selectionModel(),
&QItemSelectionModel::selectionChanged,
[&lstView1, &pLstViews](const QItemSelection&, const QItemSelection &)
{
singleSel(&lstView1, pLstViews);
});
QObject::connect(lstView2.selectionModel(),
&QItemSelectionModel::selectionChanged,
[&lstView2, &pLstViews](const QItemSelection&, const QItemSelection &)
{
singleSel(&lstView2, pLstViews);
});
QObject::connect(lstView3.selectionModel(),
&QItemSelectionModel::selectionChanged,
[&lstView3, &pLstViews](const QItemSelection&, const QItemSelection &)
{
singleSel(&lstView3, pLstViews);
});
// exec. application
return app.exec();
}
我在 Windows 10(64 位)上编译和测试。这是它的样子:
更新:
我尝试将 C++ 应用程序移植到 Python/PyQt5:
#!/usr/bin/python3
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QListView
from PyQt5.QtGui import QStandardItemModel, QStandardItem
def singleSelect(lstView, lstViews):
for lstViewI in lstViews:
if lstViewI == lstView:
continue
# the check is necessary to prevent recursions...
if lstViewI.selectionModel().hasSelection():
# ...as this causes emission of selectionChanged() signal as well:
lstViewI.selectionModel().clearSelection()
if __name__ == '__main__':
app = QApplication(sys.argv)
# build contents
tblModel = QStandardItemModel(0, 1)
for i in range(0, 10):
tblModel.appendRow(QStandardItem("Entry %d" % (i + 1)))
# build GUI
win = QWidget()
hBox = QHBoxLayout()
lstView1 = QListView()
lstView1.setSelectionMode(QListView.SingleSelection)
lstView1.setModel(tblModel)
hBox.addWidget(lstView1)
lstView2 = QListView()
lstView2.setSelectionMode(QListView.SingleSelection)
lstView2.setModel(tblModel)
hBox.addWidget(lstView2)
lstView3 = QListView()
lstView3.setSelectionMode(QListView.SingleSelection)
lstView3.setModel(tblModel)
hBox.addWidget(lstView3)
win.setLayout(hBox)
win.show()
# install signal handlers
lstViews = [lstView1, lstView2, lstView3]
lstView1.selectionModel().selectionChanged.connect(lambda sel, unsel: singleSelect(lstView1, lstViews))
lstView2.selectionModel().selectionChanged.connect(lambda sel, unsel: singleSelect(lstView2, lstViews))
lstView3.selectionModel().selectionChanged.connect(lambda sel, unsel: singleSelect(lstView3, lstViews))
# exec. application
sys.exit(app.exec_())
从我在测试中看到的情况来看,它的行为与用 C++ 编写的类似。 唯一的例外是我在更改列表视图时必须在条目上单击两次。
正如我已经说过的:我在 PyQt 方面的经验非常有限。 (实际上,我今天是从制作这个样本开始的。)因此,我可能已经监督了一些事情。请对它持保留态度...