Создание экземпляра «родного» типа QML динамически

#qt #qml

#qt #qml

Вопрос:

Возможно ли динамически выбирать между различными типами подкомпонентов (во время создания экземпляра)?

Например, некоторый псевдокод (с использованием Qt 5.9):

  //MyComp.qml
 import QtQuick 2.9
 import QtQuick.Layouts 1.3          

 Item {
   property bool useLayout: true

   //Here I want to allow the user to choose
   //whether a ColumnLayout or Column is used 
   //(e.g., by means of the useLayout property)
   ColumnLayout { //Or Column
     ...
   }
 ...
 }     
  

  //main.qml
 import QtQuick 2.9
 import QtQuick.Layouts 1.3
 import QtQuick.Controls 2.9

 ApplicationWindow {
 width: 640
 height: 480
 ...
  MyComp {
    id: a
    useLayout: false
    ...
   }
 }
  

Комментарии:

1. Может быть, вы могли бы объяснить, чего вы пытаетесь достичь этим, поскольку существуют различные способы сделать это, и правильный выбор зависит от вашего варианта использования. Некоторые из них могут быть простыми (просто используйте Loader ), а некоторые могут быть довольно сложными.

2. Я использую этот компонент MyComp изначально со списком столбцов внутри, он работает нормально, за исключением подкомпонента, помещенного в этот список столбцов: пользовательский «собственный» тип текста с включенными WordWrap и ElideRight, один за другим. Итак, когда этот текст состоит из нескольких строк, текст (свойство) появляется поверх следующего текста. Я заметил, что при использовании ColumnLayout Text.contentHeight всегда возвращает значение одной строки даже для многострочного текста, скорректированного с учетом переноса слов. Свойство lineNumber также возвращает 1. Но, если есть ‘n’, оба свойства возвращают правильные значения. Столбец, с другой стороны, работает нормально.

3. Не могли бы вы опубликовать код, иллюстрирующий проблему, которую вы только что описали в своем комментарии?

4. Я застрял с использованием пользовательского компонента, созданного другим разработчиком, который содержит Text . В документации говорится, что contentHeight и lineCount должны возвращать эти ожидаемые значения. Я полагаю, что может быть ошибка с ColumnLayout . В любом случае, я тоже попробую с Label и внесу предложение, если это сработает. Text s внутри ColumnLayout размещается статически, но text считывается во время выполнения из локальной базы данных.

5. Я решил это, установив Layout.preferredHeight свойство. Для всех, у кого такая же проблема, если содержащийся текст Text многострочный из-за переноса слов в ColumnLayout Column это работает нормально), мне пришлось соответствующим образом установить это свойство, иначе выравнивание было бы отключено. Я не смог найти никаких ссылок на это в исходной документации, так что это немного проб и ошибок. Поскольку я не упоминал об этой проблеме в исходном вопросе, я приму ответ @RickPat в качестве ответа, поскольку его решение не совсем то, что было задано, но сработало бы и в этом случае.

Ответ №1:

Я не думаю, что есть способ сделать именно то, что вы хотите, без большого количества javascript. Самый простой способ сделать это, который я могу придумать, был бы следующим. Вы могли бы сделать ColumnLayout невидимым и установить столбец в качестве родительского элемента для его дочерних элементов с помощью чего-то вроде этого:

 //MyComp.qml
import QtQuick 2.9
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.5

Item {
    property bool useLayout: true


    ColumnLayout {
        id: columnLayout

        visible: useLayout

        Component.onCompleted: {
            if (!useLayout) {
                butt1.parent = column;
                butt2.parent = column;
                butt3.parent = column;
            }
        }

        Button {
            id: butt1
            text: "butt 1"
        }
        Button {
            id: butt2
            text: "butt 2"
        }
        Button {
            id: butt3
            text: "butt 3"
        }
    }
    Column {
        id: column

        visible: !useLayout
    }
}