Qt Gui 第十章

一、QListWidget、QTableWidget和QTreeWidget

QTableWidget的item默认是可以编辑,其他两个的item默认是不可编辑。如果要将QTableWidget设置成不可编辑,可以使用

tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

则tablewidget的所有item都是不可编辑的;

QListWidget和QTreeWidget默认是不可编辑的,如果想要将item变成可以编辑的,可以简单地将item设置成可以编辑的,如下所示

        item = new QTreeWidgetItem(parent);
        item->setFlags(Qt::ItemIsEditable|item->flags());

则整个的该item是可以编辑的。如果只是想某一列可以编辑,其中一种方法是使用信号和槽。双击可编辑的方式;

复制代码
    treeWidget = new QTreeWidget;
    treeWidget->setColumnCount(2);
        。
        。
        。
    connect(treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(editFileFilter(QTreeWidgetItem*,int)));


// slot
void SettingsViewer::editFileFilter(QTreeWidgetItem *item, int column)
{
    if (column == 0)
        item->setFlags(Qt::ItemIsEditable | item->flags());
    else
        item->setFlags(item->flags() & ~(Qt::ItemIsEditable) );
}
复制代码

如上所示自己编写一个slot,当双击的时候触发设置标记

 

二、QStringListModel、QDirModel

QStringListModel 

通过QModelIndex index = model->index(row);指定的第几行获得对应的QModelIndex;

要删除行,可以通过

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

第一个要在指定的行号后面增加对应删除多少行;下面则一次只能删除一行。ps:上面两行代码都是删除一行;

可以将model装进listview里面

    model = new QStringListModel(this);
    model->setStringList(leaders);

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

第二行将QStringList leaders的数据装进model;然后将model给listview来显示(如第四行代码所示)

 

 QDirModel

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

    treeView = new QTreeView;
    treeView->setModel(model);

QDirModel装载的是文件目录;可以对文件和目录进行操作;

QModelIndex index(const QString &path, int column = 0) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;

文件查找有两种方式来获取QModelIndex; 如下所示

QModelIndex index = model->index(QDir::currentPath());

文件删除

    if (model->fileInfo(index).isDir())
        ok = model->rmdir(index);
    else
        ok = model->remove(index);

如果是目录则需要用rmdir的方式进行删除;否则通过remove进行删除文件,如上所示

创建文件夹

if (!model->mkdir(index, dirName).isValid())

 

QSortFilterProxyModel

 为model提供了代理;可以不操作model的数据,view只通过该代理类进行显示;该代理相对model增加了过滤器QRegExp;指定column还有sort,increase或者decrease等;其中sort也可以自定义排序;

    virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;

通过重写此代码进行重新自定义排序;

    virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
    virtual bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const;

可以通过重写这两个函数进行过滤指定的source_row是否需要显示,指定的source_column是否需要显示;

bool HideColumnProxy::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const
{
    if(source_column >= 3)
        return false;
    return true;
}

如上,则只显示从0~2的column号

 

三、QAbstractTableModel

当子类化QAbstractTableModel时,必须实现rowCount(),columnCount,和data()函数。因为在QAbstractItemModel中,该三个函数为纯虚函数。QAbstractItemModel另外的两个纯虚函数在QAbstractTableModel中已经被实现了,无需一定要再重写。

 当需要自定义每列或者每行的行号时,则需要重新实现函数headerData函数,例如:

QVariant CurrencyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();
    return currencyAt(section);
}

当需要更新列表的数据的时候,在qt4使用reset()函数,但是在Qt5中,却没有该函数;通过查看QAbstractItemModel的头文件可以看到:

复制代码
#if QT_DEPRECATED_SINCE(5,0)
    QT_DEPRECATED void reset()
    {
        beginResetModel();
        endResetModel();
    }
#endif

    void beginResetModel();
    void endResetModel();
复制代码

则要更新的话,需要自己用begin和end函数替代reset函数。

当需要更新数据的时候,可以重写该函数

    Q_INVOKABLE virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);

如下例子

复制代码
bool CityModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && index.row() != index.column()
            && role == Qt::EditRole) {
        int offset = offsetOf(index.row(), index.column());
        distances[offset] = value.toInt();

        QModelIndex transposedIndex = createIndex(index.column(),index.row());

        emit dataChanged(index, index);
        emit dataChanged(transposedIndex, transposedIndex);

        return true;
    }

    return false;
}
复制代码

首先index必须有效,其他两个判断则是根据实际情况进行判断的。

然后createIndex则是因为当index改变的时候,另一个index也需要改变,所以这里create了一个index;因为当在指定的范围内发生改变的时候需要emit dataChanged;因为index跟transposedIndex都发生了改变,所以都需要emit;

This signal is emitted whenever the data in an existing item changes.

返回的true或者false表示设置数据成功与否。

 

 

 

 

 

 

 

 

问题及解决:

在重写QDialog的done函数的时候,忘记在函数的最后调用父类的done函数,导致窗口无法关闭;只能通过杀死进程的方式;QDialog::done(result);

 

 

 

posted @   LCAC  阅读(405)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示