QT 提供的 QListView 和 QStringListModel, 以及QGraphicsView 和 QGraphicsScene 等,都采用了 view - model 结构,用setModel函数就可以把model 和 view 关联起来。只要model 发生变化,view 就自动更新。这里介绍用QListView 和 QStringListModel实现的选择框。
在一开始,我没有直接利用QListView,而是继承了它。这是因为我在后面要用到selectedIndexes()函数,但是这个函数是受保护的,无法直接调用,只能先用一个public函数继承它。
#include "mylistview.h" MyListView::MyListView() { <span style="color:#ff0000;">setEditTriggers(QAbstractItemView::NoEditTriggers);</span> setSelectionMode(QAbstractItemView::ExtendedSelection); } MyListView::~MyListView() { } QModelIndexList MyListView::selection() { QModelIndexList tmp = selectedIndexes();//由于selectedIndexes是受保护的,只能先用一个public函数来继承它 return tmp; }
注意红色的语句。如果没有这条语句,用户使用程序时,如果是双击了某个条目,这个条目就会进入待编辑状态。我并不想加入编辑功能,所以选择NoEditTriggers。QlistView本身的帮助文档里并没有提到NoEditTriggers,但是在它的父类QAbstractItemView里有。<pre name="code" class="cpp">
接下来是主窗口:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); mp_gLayout = new QGridLayout; mp_gLayout->setColumnStretch(0,1); mp_gLayout->setColumnStretch(1,1); mp_gLayout->setColumnStretch(2,1); mp_gLayout->setRowStretch(0,1); mp_gLayout->setRowStretch(1,1); mp_gLayout->setRowStretch(2,1); mp_ListView = new MyListView; //mp_ListView->setEditTriggers(QAbstractItemView::NoEditTriggers); mp_Model = new QStringListModel; m_QStrLst<<"123"<<"abc"<<"甲乙丙"; mp_Model->setStringList(m_QStrLst); mp_ListView->setModel(mp_Model); mp_ListView2 = new MyListView; mp_Model2 = new QStringListModel; mp_Model2->setStringList(m_QStrLst2); mp_ListView2->setModel(mp_Model2); mp_Btn1 = new QPushButton("添加 ->"); mp_Btn2 = new QPushButton("去除 <-"); mp_gLayout->addWidget(mp_ListView,0,0,3,1); mp_gLayout->addWidget(mp_ListView2, 0,2,3,1); mp_gLayout->addWidget(mp_Btn1,0,1,1,1); mp_gLayout->addWidget(mp_Btn2,1,1,1,1); ui->centralWidget->setLayout(mp_gLayout); QObject::connect(mp_Btn1, SIGNAL(clicked(bool)), this, SLOT(add())); QObject::connect(mp_Btn2, SIGNAL(clicked(bool)), this, SLOT(withdraw())); } MainWindow::~MainWindow() { delete mp_Btn1; delete mp_Model; delete mp_ListView; delete mp_Btn2; delete mp_Model2; delete mp_ListView2; delete mp_gLayout; delete ui; } void MainWindow::add() { QModelIndexList tmp = mp_ListView->selection(); for(int i=0;i<tmp.count();i++) { m_QStrLst2<<m_QStrLst.at(tmp.at(i).row()); } QSet<QString> strTmp; strTmp = m_QStrLst2.toSet();//去除重复的条目 m_QStrLst2 = strTmp.toList(); mp_Model2->setStringList(m_QStrLst2); } void MainWindow::withdraw() { QModelIndexList tmp = mp_ListView2->selection(); QList<int> iTmp; for(int j=0;j<tmp.count();j++) { iTmp<<tmp.at(j).row(); } QList<QString> lstTmp; for(int i=0;i<m_QStrLst2.count();i++) { if(!iTmp.contains(i)) lstTmp<<m_QStrLst2.at(i); } m_QStrLst2 = lstTmp; mp_Model2->setStringList(m_QStrLst2); }
这样就实现了从左边的三条目向右面导入的功能。