如何使用QModelIndex访问QTreeView中的childWidgets?

时间:2016-02-24 17:23:13

标签: c++ qt data-modeling qtreeview qstandarditem

我正在使用Qt库(版本4.8)处理应用程序。

我有一个带QStandardItemModel的QTreeView。我的小部件看起来像这样:

  

的Item1

     

subitem11

     

subitem12

     

项目2

     

subitem21

     

subitem22

     

项目3

     

subitem31

     

subitem32

以下是我将项目添加到QTreeView的方法:

 model->setItem(0, 0, item1); 
 item1->setChild(0, 0, subitem12);

我想只在用户双击项目时才采取行动(当他点击一个子项目时什么都不做)。所以我使用 doubleClicked(const QModelIndex& index)信号。

我想处理有关用户双重填充的item / subitem的信息。所以我得到了我的项目/子项目的行:

index.row();

但每次我尝试引用item / subitem来显示其名称或检查它是否有子项时,我只能访问这些项目:

index.model()->item(row)->text();

我的问题是:如何在我的插槽中访问子项目(项目abd子项目之间)?或者我怎样才能防止它们发出信号?我无法禁用它们 - 这对用户来说太麻烦了。

编辑:问题在于每次点击某个项目或子项目并执行:

index.model()->item(row)->hasChildren();

或:

index.model()->item(row)->parent() == 0;

结果是 true 。所以我只能参考这些项目。

我的问题是:引用子项目的正确方法是什么?

3 个答案:

答案 0 :(得分:2)

当您尝试按行索引访问模型项时,模型将返回该行的顶级项。请改用itemFromIndex

auto item = index.model()->itemFromIndex(index);
if (item && item->hasChildren()){
    // item is not a leaf
}

编辑 index.model()返回QAbstractItemModel*,因此这里也需要强制转换(或者更好的是,在代码中存储指向标准模型的指针)。

答案 1 :(得分:0)

您无法禁用子项的信号。但是,您可以检查项目是否具有父项。它不是,它是一个项目,如果它,它是一个子项目。

if (item->parent() != 0)
   .. //subitem
else
   .. //item

另一种方法是使用data()函数设置一些特殊值来区分两者。

item1->setData(QVariant("item"));
subitem1->setData(QVariant("subitem"));

然后在doubleclick处理程序中查询值:

QVariant var = item->data();
if (var.toString() == "item")
  ...
else if (var.toString() == "subitem")
  ...

答案 2 :(得分:0)

我会这样做:

// Define your custom role to store item type.
enum MyRoles
{
    ItemTypeRole = Qt::UserRole + 1
};

// Define item types.
enum ItemType
{
    Primary,
    Secondary
};

为所有项目设置正确的项目类型

QStandardItem* item = new QStandardItem("Item1");
item->setData(Primary, ItemTypeRole);

QStandardItem* subItem = new QStandardItem("SubItem1");
subItem->setData(Secondary, ItemTypeRole);

在连接到 doubleClicked 信号的插槽中,访问类似这样的类型:

ItemType type = static_cast<ItemType>(index.data(ItemTypeRole).toInt());
if (type == Primary)
    std::cout << "It's a Primary item!" << std::endl;
else if (type == Secondary)
    std::cout << "It's a Secondary item!" << std::endl;