Подтвердить что ты не робот

Как сделать "is_a", "typeof" или instanceof в QML?

Я хочу запустить список компонентов QML и выбрать один тип:

for (var i = 0; i < controls.children.length; ++i) {
     if ( typeof (controls.children[i].height) == "QDeclarativeRectangle")
     {
        // do stuff
     }
}

Как это сделать?

4b9b3361

Ответ 1

Вы не можете использовать typeof для этого напрямую, потому что он всегда будет возвращать вам 'object' как тип любого элемента QML. Однако есть несколько альтернатив, которые вы могли бы использовать. Один из них устанавливает objectName каждого элемента в свой тип и проверяет это в вашем цикле или определяет свойство и проверяет его. Для этого потребуется немного больше работы, но вы можете создать свой элемент qml, обладающий этим свойством, и использовать его там, где вам это нужно. Вот пример кода:

Rectangle {
  id: main
  width: 300; height: 400

  Rectangle {
    id: testRect
    objectName: "rect"
    property int typeId: 1
  }

  Item {
    id: testItem
    objectName: "other"
  }

  Component.onCompleted: {
    for(var i = 0; i < main.children.length; ++i)
    {
        if(main.children[i].objectName === "rect")
        {
            console.log("got one rect")
        }
        else
        {
            console.log("non rect")
        }
    }
    for(i = 0; i < main.children.length; ++i)
    {
        if(main.children[i].typeId === 1)
        {
            console.log("got one rect")
        }
        else
        {
            console.log("non rect")
        }
    }
  }
}

Ответ 2

Здесь другой подход, использующий toString() (который может быть не переносимым в будущую версию QML):

function qmltypeof(obj, className) { // QtObject, string -> bool
  // className plus "(" is the class instance without modification
  // className plus "_QML" is the class instance with user-defined properties
  var str = obj.toString();
  return str.indexOf(className + "(") == 0 || str.indexOf(className + "_QML") == 0;
}

...

for (var i = 0; i < controls.children.length; ++i) {
   if (qmltypeof(controls.children[i].height, "QDeclarativeRectangle"))
   {
     // do stuff
   }
}

Ответ 3

Да, эта нить составляет 2 года, но, возможно, мой ответ может помочь кому-то там.

Для меня было достаточно использовать JSON.stringify() для сравнения элементов QML. Конечно, если два разных элемента имеют точно такие же свойства и значения, это даст вам ложный результат. (например, когда один элемент находится поверх другого с тем же цветом, x, y и т.д.)

toString() не работал у меня, так как я создал много экземпляров из одного базового компонента. Установка objectName для каждого экземпляра была бы слишком большой для моего использования.

Ответ 4

Так как Qt 5.10, вы можете, наконец, использовать instanceOf, чтобы проверить, имеет ли переменная определенный тип QML: https://v-play.net/updates/v-play-2-15-0-qt-5-10-qt-creator-4-5-support-firebase-data-structures-and-queries#qt-5-10-qml-enum-instanceof

import VPlayApps 1.0
import QtQuick 2.0

App {
  // two QML items, used for type checking
  Item { id: testItem }
  Rectangle { id: testRect }

  // function to check wheter an item is a Rectangle
  function isRectangle(item) {
    return item instanceof Rectangle
  }

  // type check example
  Component.onCompleted: {
    console.log("testItem is Rectangle? "+isRectangle(testItem))
    console.log("testRect is Rectangle? "+isRectangle(testRect))
  }
}