2017-08-04 48 views
0

我有几个QListWidget s,并希望只允许为所有这些列表选择一个单一的行。例如,如果我在其中一个列表中选择一行,其他列表中的其他列表中的任何其他列表都将被清除。我怎样才能做到这一点?Qt:多个QListWidgets,只有一个选择的条目

有没有一个内置的方式来做到这一点(类似QButtonGroup的按钮)?如果不是,那么当您尝试自己实现这个功能时,您会建议采取什么方法?

为感谢帮助与亲切的问候, 托德

+2

写出每个列表窗口小部件,其未选中所有其他列表控件的信号处理程序。 AFAIK没有现成的内置。 (你可能要小心:取消选择可火RESP选择信号,以及因此,你应该考虑某种锁定对递归的。) – Scheff

回答

1

据我所知,没有现成的内置功能,以提供多个列表视图中进行单项选择。

相反,它可以通过为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位)进行测试。这是它的外观:

Snapshot of testQSingleSelectInMultipleListViews


更新:

我试图端口的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++编写的。 唯一的例外是当我更改列表视图时,我必须在条目上单击两次。

Snapshot of testQSingleSelectInMultipleListViews.py

正如我已经说过:我在PyQt的经验是非常有限的。 (实际上,我今天开始做这个样本。)因此,我可能会监督一些事情。请采取与一粒盐...

+0

@sunyata我做了一个端口到Python3/PyQt5。它看起来并不坏...但请考虑我在文本结尾的“免责声明”。 – Scheff