QListView 使用

一.简介

   QListView 是 Qt 中用于显示列表数据的控件。

         它是 MVC(模型-视图-控制器)架构的一部分,通常与 QAbstractListModel 或其子类结合使用;
         使用QListView 可以使用设计界面拖拽或者使用代码编写;

二.数据填充

1.简单数据填充
        比如字符串列表QStringList

QStringList dataList = {"Item 1", "Item 2", "Item 3"};
QStringListModel *model = new QStringListModel(dataList);
ui->listView->setModel(model);

        创建了一个字符串列表,并使用 QStringListModel 将其设置为 QListView 的模型。这样,列表视图就会展示出这些字符串。

2.自定义模型
        a.使用字符串列表

#include <QAbstractListModel>
#include <QListView>
#include <QStringList>

class MyModel : public QAbstractListModel
{
    Q_OBJECT

public:
    MyModel(QObject *parent = nullptr)
        : QAbstractListModel(parent)
    {
        m_data << "item1" << "item2" << "item3";
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        Q_UNUSED(parent);
        return m_data.count();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
    {
        if (!index.isValid())
            return QVariant();

        if (index.row() >= m_data.size())
            return QVariant();

        if (role == Qt::DisplayRole)
            return m_data.at(index.row());
        else
            return QVariant();
    }

private:
    QStringList m_data;
};

        这是一个最基本的自定义数据模型,rowCount 方法返回项的总数,而 data 方法根据索引返回相应的数据。自定义模型实际并非如此简单.里面还涉及到数据修改.角色项等.这个后面单独写一篇吧.
3.数据库数据绑定

        当数据存储在数据库中时,您可以使用 QSqlTableModel 来将数据绑定到 QListView。这个模型提供了一个接口来读取和写入数据库表。

#include <QSqlTableModel>
#include <QListView>

//执行以下代码前提是数据库已经打开;
以下代码只是演示如何使用数据库数据绑定到view

QSqlTableModel *tableModel = new QSqlTableModel;
tableModel->setTable("your_table_name");
tableModel->select();

ui->listView->setModel(tableModel);

        在这段代码中,我们指定了要操作的数据库表,并通过调用 select 方法加载了数据。然后,我们将模型设置到 QListView,数据库中的数据就会显示在列表视图中。


三.自定义委托以及外观

1.自定义委托
        a.使用Qt现有控件,比如按钮

//继承QItemDelegate该类也是可以的,只是目前新的基本都继承QStyledItemDelegate 更加灵活

class ButtonDelegate : public QStyledItemDelegate {
public:
    ButtonDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
        QPushButton *editor = new QPushButton(parent);
        // 这里可以设置按钮的属性,例如文本、图标等
        return editor;
    }

    void setEditorData(QWidget *editor, const QModelIndex &index) const override {
        QPushButton *button = static_cast<QPushButton*>(editor);
        // 根据模型数据设置按钮的显示
        QString value = index.model()->data(index, Qt::DisplayRole).toString();
        button->setText(value);
    }
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const             
    QModelIndex &index) const override {
        editor->setGeometry(option.rect);
    }
};


        b.使用自绘
        

#include <QStyledItemDelegate>
#include <QPainter>

class ButtonDelegate : public QStyledItemDelegate {
    Q_OBJECT
public:
    ButtonDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
        QStyleOptionButton button;
        button.rect = option.rect.adjusted(4, 4, -4, -4); 
        button.text = index.model()->data(index, Qt::DisplayRole).toString();
        button.state = QStyle::State_Enabled;

        QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
    }

    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override {
        if (event->type() == QEvent::MouseButtonRelease) {
            // 在这里处理按钮点击事件
            emit buttonClicked(index);
            return true;
        }
        return false;
    }

signals:
    void buttonClicked(const QModelIndex &index);
};

四.复杂数据处理     

要在 QListView 中展示复杂的数据结构,并利用角色(Roles)和自定义数据模型,需要以下几个步骤:

  1. 定义复杂数据结构: 首先,定义一个复杂的数据结构。例如,一个包含多个字段的类或结构体。

  2. 创建自定义数据模型: 创建一个继承自 QAbstractListModelQAbstractItemModel 的自定义模型类。在这个模型类中,实现必要的方法,如 data()rowCount()roleNames()

  3. 实现角色(Roles): 在自定义模型中,定义额外的角色来代表数据结构中的不同元素。这通常是通过在 roleNames() 方法中返回一个角色名与角色值的映射来完成的。

  4. 填充模型数据: 填充自定义模型的数据。这涉及到将复杂数据结构的实例添加到模型中。

  5. QListView 中使用模型: 创建 QListView 的实例,并将自定义模型设置给它。

自定义委托(可选): 如果需要,可以创建一个自定义委托来自定义数据项的呈现方式。
 

class MyData {
public:
    QString name;
    int age;
};

class MyModel : public QAbstractListModel {
    Q_OBJECT

public:
    enum DataRoles {
        NameRole = Qt::UserRole + 1,
        AgeRole
    };

    MyModel(QObject *parent = nullptr) : QAbstractListModel(parent) {
        
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override {
        return dataList.size();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
        if (!index.isValid() || index.row() >= dataList.size())
            return QVariant();

        const MyData &item = dataList.at(index.row());
        switch (role) {
            case NameRole:
                return item.name;
            case AgeRole:
                return item.age;
            
            default:
                return QVariant();
        }
    }

    QHash<int, QByteArray> roleNames() const override {
        QHash<int, QByteArray> roles;
        roles[NameRole] = "name";
        roles[AgeRole] = "age";
       
        return roles;
    }

private:
    QList<MyData> dataList;
    
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MyModel model;
    // 填充模型数据
    // ...

    QListView listView;
    listView.setModel(&model);
    listView.show();

    return app.exec();
}

使用如自定义模型.只是将其代理数据从字符串列表更换为了类列表.当然,使用结构体等其他数据类型也是可以的.某些时候.若是在信号里面传输自定义数据结构.需要注册到Qt的元对象系统;
 

五.高级定制

要高级定制 QListView,涉及到视觉效果的定制、性能优化以及交互功能的增强。下面是具体的实现步骤和代码示例:

1. 视觉效果定制

a. 自定义外观

可以通过重写 paint 方法或使用 Qt 样式表(QSS)来自定义 QListView 的外观。

使用样式表示例

一般来说.做项目的时候会单独写一个qss文件.作为整个程序的外观文件,并全局加载.

listView->setStyleSheet("QListView {"
                        "    background-color: #f0f0f0;"
                        "    color: #333;"
                        "    border: 1px solid #ddd;"
                        "}"
                        "QListView::item {"
                        "    padding: 5px;"
                        "}"
                        "QListView::item:selected {"
                        "    background-color: #3399ff;"
                        "    color: white;"
                        "}");

2. 性能优化

a. 面对大量数据的性能考虑

对于大量数据,应考虑使用合适的数据结构和高效的模型更新方法。使用 beginInsertRowsendInsertRows 来批量添加或删除项目。

b. 延迟加载和视图的虚拟化

延迟加载(Lazy Loading)是指仅在需要显示数据时才加载它们。可以通过在模型的 data 方法中实现按需加载来达到这个目的。

3. 交互增强

交互增强对于 QListView 而言,主要包括实现拖放、排序和过滤等功能。这些功能可以显著提高用户体验,尤其是在处理大量数据项的时候。以下是每个功能的具体实现方法:

1. 拖放功能

为了在 QListView 中启用拖放功能,您需要设置相应的属性,并实现所需的事件处理。

a. 启用拖放: 首先,开启 QListView 的拖放功能,并设置拖放模式。

listView->setDragEnabled(true);               // 启用拖拽
listView->viewport()->setAcceptDrops(true);   // 接受拖放
listView->setDropIndicatorShown(true);        // 显示拖放指示器
listView->setDragDropMode(QAbstractItemView::InternalMove); // 设置拖放模式

b. 实现拖放事件: 您可能需要重写以下方法来自定义拖放行为:

  • dragEnterEvent(QDragEnterEvent *event):处理拖动进入视图的事件。
  • dragMoveEvent(QDragMoveEvent *event):处理拖动时的事件。
  • dropEvent(QDropEvent *event):处理放置操作的事件。

2. 排序功能

要实现排序功能,通常需要使用 QSortFilterProxyModel 作为模型的代理。

a. 设置代理模型: 创建一个 QSortFilterProxyModel 实例,并将其设置为模型的代理。

QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(listView);
proxyModel->setSourceModel(yourModel);  // yourModel 是原始数据模型
listView->setModel(proxyModel);

b. 启用和实现排序: 通过点击列头或使用代码来触发排序。

proxyModel->setSortRole(Qt::UserRole);   // 设置排序所依据的角色
proxyModel->sort(0, Qt::AscendingOrder); // 根据第一列进行升序排序

3. 过滤功能

过滤功能也可以通过 QSortFilterProxyModel 实现。

a. 设置过滤条件: 设置过滤角色和过滤规则。

proxyModel->setFilterRole(Qt::DisplayRole);   // 设置过滤所依据的角色
proxyModel->setFilterRegExp(QRegExp("过滤条件", Qt::CaseInsensitive, QRegExp::FixedString));

b. 动态过滤: 您可以根据用户输入或其他条件动态更改过滤规则。

void updateFilter(const QString &text) {
    proxyModel->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString));
}

通过以上步骤,您可以为 QListView 实现丰富的交互功能,使其更加动态和易用。

结论

QListview相较于QListWidget更加灵活多变.拥有更多的可塑性.

  • 22
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值