c++ - 从模型中获取下一个项目

标签 c++ qt qml qt5

我已经创建了 GridView , 它委托(delegate)自定义对象 ( Item ) 并且其模型派生自 QSortFilterProxyModel .目前,每当我点击 GridView 中的项目时,它显示了一些关于它的信息,但目前我正在尝试用键盘箭头控制它,所以我需要帮助功能,它获取下一个/上一个项目。

我想出了一些解决办法:

  • 获取GridView中当前选中项的索引,我设法做到了:

    console.log(slabItemContainer.contentItem.data[index]) ,但我没有弄清楚如何从索引中取回委托(delegate)(因为我不需要 QQuickItem ,但我需要指向 Item 的指针)。我为 Item 设置了角色名称作为 "item" ,所以每当我写 console.log(item) 行时, 它显示了正确的对象,但我没能从 QQuickItem 得到它按索引。

  • QSortFilterProxyModel 派生的模型中获取自定义对象

我试图得到某种 QList从我的模型,但我不知道如何访问数据。我的模型包含指向当前选定的指针 Item ,所以我试图从我的模型中获取整个列表,然后找到当前选择的项目然后设置下一个,但我什至没有创建列表,因为我不知道如何访问它。 我试过使用 mapToSource() , 但没有成功。

QModelIndex modelIndex = this->index(0,0, QModelIndex()); qDebug() << mapToSource(modelIndex);

点击 ItemGridView版画 Item(0x2d508408) , 这打印出我 QModelIndex(0,0,0x0,ItemModel(0x2d528210)) ,但同样,我不知道如何从中获取数据。

有没有人有这方面的经验?我应该如何通过当前项目获取下一个项目?

感谢您的帮助!

//编辑:

Filter.h

#include <QSortFilterProxyModel>
#include "Item.h"

class MyModel : public QSortFilterProxyModel
{
    Q_OBJECT
    Q_PROPERTY(Item* currentDetailView READ currentDetailView WRITE setFilterCurrentDetailView NOTIFY currentDetailViewChanged)

public:
    ItemFilterSortModel(QObject *parent = 0);

    //! Return true, if entity matches with filter conditions
    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;

    //! Returns Item to load into view
    Item * currentDetailView() const {return currentDetailView_;}

    //! Set up currently showing detail of Item
    Q_INVOKABLE void setFilterCurrentDetailView(Item *ItemToView);

    Q_INVOKABLE Item * getFilterNextDetailView();

    Q_INVOKABLE Item * getFilterPrevDetailView();

signals:
    currentDetailViewChanged();

private:
    Item *currentDetailView_;
};

过滤器.cpp

#include "MyModel.h"

ItemFilterSortModel::ItemFilterSortModel(QObject *parent)
    : QSortFilterProxyModel(parent)
{

}

bool ItemFilterSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
    QModelIndex modelIndex = sourceModel()->index(source_row, 0, source_parent);

    //Checking conditions for displaying Item into gridview
    return (foo(sourceModel()->data(modelIndex,confidenceRole).toDouble()));
}

Item *ItemFilterSortModel::getFilterNextDetailView()
{
    QModelIndex modelIndex = this->index(0,0, QModelIndex());
    qDebug() << mapToSource(modelIndex);
}

Item *ItemFilterSortModel::getFilterPrevDetailView()
{

}

GridView.qml

GridView {    
            model: slabGridModel.filterModel
            delegate: Item{
                height: slabItemContainer.cellHeight - 15
                width: slabItemContainer.cellWidth - 15
            }
            Action {
                 shortcut: "Right"
                 onTriggered: model.getFilterNextDetailView()
            }
        }

//编辑:

按下右箭头键时屏幕上会发生这种情况 What happens to screen when right arrow key is pressed

//编辑:

ItemModel.h

#include "Item.h"
#include <QAbstractListModel>
#include <QSortFilterProxyModel>

class ItemModel : public QAbstractListModel
{
    Q_OBJECT

public:
    // ---- PUBLIC METHODS ----
    //! Deletes items in list
    ~ItemModel();

    //! Returns number of items in list
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    //! Exposes data of Items to QML by their roles
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    //! Appends the Item into Item list
    void appendItem(Item * Item);

    //! Sets up role names for exposing them to QML
    QHash<int, QByteArray> roleNames() const;

    //! Returns list of all available Items
    QList<Item *> getItemList() const { return ItemList_; }

private:
    // ---- PRIVATE ATTRIBUTES ----
    QList<Item *> ItemList_;
};

ItemModel.cpp

#include "ItemModel.h"

ItemModel::~ItemModel(){
    qDeleteAll(ItemList_);
    ItemList_.clear();
}

int ItemModel::rowCount(const QModelIndex &parent) const{
    return parent.isValid() ? 0 : ItemList_.size();
}

QVariant ItemModel::data(const QModelIndex &index, int role) const{
    switch (role) {
    case Qt::UserRole:
        {
            Item *Item =  ItemList_[index.row()];
            return QVariant::fromValue(Item);
        }
        break;
    default:
        return QVariant();
        break;
    }
}

void ItemModel::appendItem(Item *Item)
{
    ItemList_.append(Item);
}

QHash<int, QByteArray> ItemModel::roleNames() const{
    QHash<int, QByteArray> roles;
    roles[Qt::UserRole] = "item";
    return roles;
}

最佳答案

使用我的 previous answer因为我认为您正在使用它作为代码的基础,所以我们可以在 QML 中获得以下元素,因为当您使用代理时,以下是模型方面的相关元素,因为正如您在图中所示,以下是视觉效果理念:

itemfiltersortmodel.h

#ifndef FILTERPROXYMODEL_H
#define FILTERPROXYMODEL_H

#include "item.h"

#include <QSortFilterProxyModel>
#include <QDebug>

class ItemFilterProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
    Q_PROPERTY(Item* currentItem READ currentItem WRITE setCurrentItem NOTIFY currentItemChanged)
public:
    using QSortFilterProxyModel::QSortFilterProxyModel;
    Item *currentItem()
    {
        return mCurrentItem;
    }
    void setCurrentItem(Item *currentItem)
    {
        qDebug()<<currentItem;
        if(mCurrentItem == currentItem)
            return;
        mCurrentItem = currentItem;
        emit currentItemChanged();
    }
    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
    {
        // foo process
        return true;
    }
signals:
    void currentItemChanged();
private:
    Item *mCurrentItem;
};

#endif // FILTERPROXYMODEL_H

ma​​in.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    GridView {
        id: gv
        anchors.fill: parent
        model: manager.filterModel
        property int nextIndex : mod(currentIndex+1, count)
        property int previousIndex : mod(currentIndex-1, count)
        property var currentModelItem
        onCurrentModelItemChanged: model.currentItem = currentModelItem
        delegate:
            Rectangle {
            width: 100
            height: 100
            property var view: GridView.view
            property bool isCurrentItem: index === view.currentIndex
            property bool isPreviousItem : index === view.nextIndex
            property bool isNextItem : index === view.previousIndex
            color: isCurrentItem ? "red" : isNextItem ? "green"  : isPreviousItem ? "blue" : "yellow"
            rotation: isCurrentItem ? 180 : isNextItem ? 90  : isPreviousItem? -90  : 0
            onIsNextItemChanged: if(isNextItem) view.currentModelItem = modelData
            Text {
                text: modelData.getVar
                anchors.centerIn: parent
            }
        }
    }
    // https://stackoverflow.com/a/50770689/6622587
    function mod(n, p){
        var r = n % p;
        return r < 0 ? r + p : r;
    }
    Action {
        shortcut: "Right"
        onTriggered: gv.currentIndex = mod(gv.currentIndex + 1, gv.count)

    }
    Action {
        shortcut: "Left"
        onTriggered: gv.currentIndex = mod(gv.currentIndex - 1, gv.count)
    }
}

enter image description here

颜色:

  • 上一个:蓝色
  • 当前:红色
  • 下一个:绿色

您可以在下面的link中找到完整的代码.

关于c++ - 从模型中获取下一个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51364623/

相关文章:

c++ - 如何在 QStyledItemDelegate::paint() 中获取 QListView 的 currentIndex

c++ - 当子任务具有很强的相互依赖性时,如何构建一个大例程

c++ - 从另一个类启动 QTimer

c++ - Qt3D:如何使用Qt C++在线框模式下渲染网格?

c++ - 为 console.log 设置一个 QML 类别

qml - 更改模型不会影响 ComboBox

qt - 如何将焦点设置到 ListView 委托(delegate)内的 TextField?

c++ - c++ Qt多线程应用程序中删除指针导致崩溃

c++ - 一种无需 XAML 即可关闭 DirectX Metro 应用程序的方法

c++ - 如何从 qmake 定义类型?预包含头文件?