MV/D视图总结

一、使用项视图
项视图(item view)
item view convenience classes use a clssic item-based interface
rather than a pure model/view approach.

list items are typically used to display text() and an icon()

1.QListWidget
默认是只读的
通过QListWidgetItem *item = new QListWidgetItem()
additem()函数将QListWidgetItem加入到QListWidget显示
2.QTableWidget
默认是可编辑的
QTableWidgetItem类为QTableWidget提供项
setitem()是插入的方法
setVerticalHeaderLabels()
setHorizontalHeaderLabels()
设置表头
3.QTreeWidget
默认是只读的
QListWidgetItem类为QTreeWidget提供项

上面三个类是为视图提供了一个简便的方法,因为它们已经有了默认的或者预置的model
我们只要将相应的项编辑然后加进去即可

二、下面介绍使用MV/D方法视图


model代表数据,它对数据的存取负责,为视图提供相同的API
view代表面向用户的数据
delegate,用于对项的显示和编辑提供精细控制。
Qt对每种类型的视图提供默认的委托。
model与view分开,可以让一个model支持多个同步的view,而且各自修改,互不影响。

model和view通过QModelIndex类实例连接起来。
QModelIndex主要是为了指明model中项的位置。QModelIndex实例有自己的行,列信息,有
父对象,兄弟对象,和子对象信息
还能携带有关model位置项的data(),flag(),internalId()的信息。还有一个

internalPointer()指针。
一般常用的只有位置信息了。

 

QStringListModel
一般类中会有两个成员:QListView和QStringListModel两个实例
使用实例:
model = new QStringListModel(this);
    model->setStringList(leaders);

    listView = new QListView;
    listView->setModel(model);
    listView->setEditTriggers(QAbstractItemView::AnyKeyPressed
                              | QAbstractItemView::DoubleClicked);

当要对view中的内容修改时,要修改model
使用实例
   int row = listView->currentIndex().row();
    model->insertRows(row, 1);

    QModelIndex index = model->index(row);
    listView->setCurrentIndex(index);
    listView->edit(index);

model->removeRows(listView->currentIndex().row(), 1);

QStringListModel封装了QStringList,为view提供了操作接口,它的QModelIndex

最后要注意的是,当使用完可修改的model后,要提供一个返回model修改后内容的方法

return model->stringList();

QDirModel操作实例
    model = new QDirModel;
    model->setReadOnly(false);
    model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name);

    treeView = new QTreeView;
    treeView->setModel(model);
    treeView->header()->setStretchLastSection(true);

    treeView->header()->setSortIndicator(0, Qt::AscendingOrder);
    treeView->header()->setSortIndicatorShown(true);
    treeView->header()->setClickable(true);

model->mkdir(index, dirName);
model->fileInfo(index);
model->rmdir(index);
model->remove(index);

QSortFilterProxyModel

The QSortFilterProxyModel class provides support for sorting and filtering data

passed between another model and a view.

(也就是,它必须要依赖一个model或者view才能使用)
QSortFilterProxyModel can be used for sorting items, filtering out items, or both.

The model transforms the structure of a source model by mapping the model indexes

it supplies to new indexes, corresponding to different locations, for views to

use. This approach allows a given source model to be restructured as far as views

are concerned without requiring any transformations on the underlying data, and

without duplicating the data in memory.
使用eg:


    sourceModel = new QStringListModel(this);
    sourceModel->setStringList(QColor::colorNames());

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(sourceModel);
    proxyModel->setFilterKeyColumn(0);

    listView = new QListView;
    listView->setModel(proxyModel);
    listView->setEditTriggers(QAbstractItemView::NoEditTriggers);

 

   QRegExp::PatternSyntax syntax =
            QRegExp::PatternSyntax(syntaxComboBox->itemData(
                    syntaxComboBox->currentIndex()).toInt());
    QRegExp regExp(filterLineEdit->text(), Qt::CaseInsensitive, syntax);
    proxyModel->setFilterRegExp(regExp);


自定义model


QAbstractTableModel
根据subclassing介绍,要重新实现rowCount(),columnCount()和data()三个函数
修改表头:headerData()
如果要让QAbstractTableModel变得可编辑,就要重新实现
setData()和flags()
setData()主要是将view中取得的数据在底层更新,注意在数据更新完后,要发射

dataChanged()信号
data()主要是将底层的数据取出返回给view
flags()主要是将Qt::ItemIsEditable标志加到flags里。

QAbstractItemModel
它不是方便的子类,继承这个model除了要实现rowCount(),columnCount()和data()三个函数

外,还要实现index(), parent()这两个函数。
如果要实现层次模型,在创建index()时,可将index的内部指针指向一个内部的节点

三、delegate

QItemDelegate
     它能够为QAbstractItemView子类提供个性化的显示特性和编辑部件。能够让显示和编辑在
model和view中独立。
QStyledItemDelegate已经接管了QItemDelegate的工作,所以在创建新的delegates时建议使

用QStyledItemDelegate。

在标准view中显示model项时,可以简单地让model返回正确角色值。如果想有更多地控制就需

要用户自己创建delegate
QAbstractItemDelegate已经提供了 paint() ,sizeHint()虚函数。用户要重新实现它们。
当view被编辑时,要有一个编辑部件。使用QItemEditorFactory创建编辑部件,

QItemDelegate中已有了默认的编辑部件,用户可以使用setItemEditorFactory()来设置自己

的编辑部件,或 QItemEditorFactory::setDefaultFactory()设置默认的编辑部件。
被编辑的model中的数据是放在Qt::EditRole角色里。
可重新实现的函数
createEditor()返回一个编辑部件。
setEditorData()提供给编辑部件数据
updateEditorGeometry(),保证编辑部件有一个正确的显示位置和大小
setModelData(),将数据更新到model中。
closeEditor()信号表示数据编辑完成,可以销毁编辑部件

 

使用eg:

//为窗口部件设置一个delegate

         tableWidget= newQTableWidget(tracks->count(),2);

    tableWidget->setItemDelegate(new TrackDelegate(1));

实现自定义的delegate

void TrackDelegate::paint(QPainter*painter,

                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        int secs = index.model()->data(index, Qt::DisplayRole).toInt();
        QString text = QString("%1:%2")
                       .arg(secs / 60, 2, 10, QChar('0'))
                       .arg(secs % 60, 2, 10, QChar('0'));
 
        QStyleOptionViewItem myOption = option;
        myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
 
        drawDisplay(painter, myOption, myOption.rect, text);
        drawFocus(painter, myOption, myOption.rect);
    } else{
        QItemDelegate::paint(painter, option, index);
    }
}
 
//当用户初始化编辑的时候,会调用createEditor(),然后调用setEditorData()
//初始化编辑器的数据。当用户按下了enter键,或者单击了编辑框以外的空间,
//就会调用setModelData()函数
 
QWidget *TrackDelegate::createEditor(QWidget *parent,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        QTimeEdit *timeEdit = new QTimeEdit(parent);
        timeEdit->setDisplayFormat("mm:ss");
        connect(timeEdit, SIGNAL(editingFinished()),
                this, SLOT(commitAndCloseEditor()));
        return timeEdit;
    } else {
        return QItemDelegate::createEditor(parent, option, index);
    }
}
 
void TrackDelegate::setEditorData(QWidget *editor,
                                  const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        int secs = index.model()->data(index, Qt::DisplayRole).toInt();
        QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor);
        timeEdit->setTime(QTime(0, secs / 60, secs % 60));
    } else {
        QItemDelegate::setEditorData(editor, index);
    }
}
 
void TrackDelegate::setModelData(QWidget *editor,
                                 QAbstractItemModel *model,
                                 const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor);
        QTime time = timeEdit->time();
        int secs = (time.minute() * 60) + time.second();
        model->setData(index, secs);
    } else {
        QItemDelegate::setModelData(editor, model, index);
    }
}
 
void TrackDelegate::commitAndCloseEditor()
{
    QTimeEdit *editor = qobject_cast<QTimeEdit *>(sender());
    emit commitData(editor);//通知视图用被编辑的数据替换已经存在的数据
    emit closeEditor(editor);//通知视图删除编辑器
}

 

 

自定义view

继承QAbstractItemView中的所有纯虚函数都必须进行声明,这些必须声明的纯虚函数包括
visualRect(),scrollTo(),indexAt(),moveCursor(),horizontalOffset(),verticalOffset

(),isIndexHidden(),setSelection()和visualRegionForSelecion(),这些函数并不一实都要

实现,根据功能要求选择实现。


保用paintEvent()实现自定义view的绘制工作。
创建绘图设备
QPainter painter(viewport());
数据来源:
QModelIndex index = model()->index(row, 0, rootIndex());
QString dep = model()->data(index).toString();
 
if (selections->isSelected(index))
{
}
选择区的处理
重现mousePressEvent,根据mouse的position,画一个小矩形,
然后判断小矩形和index关联的矩形是否有交集,如果有,就返回
一个index.
调用:selections->select(selectedIndex,flags);确定选择的索引


indexAt()
根据viewport在位置,返回一个index

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值