2013-11-27 1 views
3

QML 파일 자체가 여러 개의 QML 항목 (개별 파일로 구성)을 표시하는 QQuickView이 있습니다. C++ 코드를 사용하여 항목을 동적으로 추가하고 싶습니다. 동적으로 추가 된 항목은 상위 항목 (예 : widthheight 속성 참조 상위)과 크기를 조정해야합니다. 예를 들어동적으로 C++ 생성 QML 항목이 다른 기존 항목을 인식하지 못하는 이유는 무엇입니까?

는 QML 내 대상 항목은 다음과 같습니다가 :

// TargetContainer.qml 

Grid { 
    id: fillMeWithItemsContainer 
    objectName: "fillMeWithItemsContainer" 
} 

나는 동적으로 (아마도 여러 번) 추가 할 항목과 같습니다

// DynamicItem.qml 

Rectangle { 
    color: "white" 

    height: fillMeWithItemsContainer.height 
    width: height * 4/3 
} 

참고 그 직사각형은 높이와 관련된 컨테이너를 참조합니다.

quickViewTargetContainer로 채워집니다 :

QQuickView *quickView = new QQuickView(); 
quickView->setSource(QUrl("qrc:/foo/bar/TargetContainer.qml")); 

그래서 나는 구성 요소

QQmlComponent dynamicallyLoadedComponent(
       quickView->engine(), 
       QUrl("qrc:/foo/bar/DynamicItem.qml") 
       ); 

를로드 그리고 나는 그것의 개체를 만들 수 있습니다. 그것은 이전에 생성되어 있기 때문에,

DynamicItem.qml:4: ReferenceError: fillMeWithItemsContainer is not defined 

quickView

fillMeWithItemsContainer의 존재를 알고 있어야합니다
QObject *dynamicallyLoadedObject = dynamicallyLoadedComponent.create(); 

여기에 내가 (응용 프로그램 출력보기에서) 오류를 얻을. 그러나 fillMeWithItemsContainer은 (아직) dynamicallyLoadedObject의 부모가 아니며 문제가 될 수 있습니다. QObject (내가 전에 dynamicallyLoadedObject->setParent()을 시도하지만, 이것은 부모의 다른 종류의 것 같다 :

그래서 나는

QQuickItem *targetItem = quickView->rootObject()->findChild<QQuickItem*>("fillMeWithItemsContainer"); 

하여 대상 항목을 찾아 이전에 생성 된 객체를

dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem)); 

참고 reparent 대 부모 재산).

그러나 dynamicallyLoadedObject의 너비 및 높이 속성은 0으로 설정됩니다 (참조 오류로 인해). 변경되지 않습니다. 프로그래밍 방식으로 다시 설정하더라도

dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;"); 
dynamicallyLoadedObject->setProperty("width", "height * 4/3"); 

아무 것도 변경되지 않습니다.

나는 그것이 작동 직접 QML에서 DynamicItem을 정의하는 경우 :

Grid { 
    id: fillMeWithItemsContainer 
    objectName: "fillMeWithItemsContainer" 

    DynamicItem {} 
} 

가 어떻게 동적으로 추가 된 항목은 전에 QML보기에 된 항목에 액세스 할 수 있는지 확인합니까? 대안 : 내가 뭘 잘못하고 있니?

답변

5
dynamicallyLoadedObject->setProperty("height", "fillMeWithItemsContainer.height;"); 
dynamicallyLoadedObject->setProperty("width", "height * 4/3"); 

이것은 실제로 속성에 대한 JavaScript 바인딩을 설정하지 않습니다. 대신, 예를 들어 문자열 "fillMeWithItemsContainer.height;"을 속성에 입력합니다.이 속성은 속성이 int이고 형식이 QString이 아니므로 실패합니다. C++에서는 실제로 속성에 바인딩을 할당 할 수 없습니다 (일부 예외는 QQmlBinding 등).

dynamicallyLoadedObject->setProperty("parent", QVariant::fromValue<QObject*>(targetItem)); 

세르게이 언급 한 바와 같이, 당신은 parent 속성을 설정하는 대신 QQuickItem::setParentItem를 호출해야합니다. 이는 일반 문자열 기반 setProperty API보다 조금 더 유형 안전합니다. 상위 항목이 없으면 QQuickItem은 표시되지 않습니다. 부모 키는 부모 항목 만 변경하므로 레이아웃 및 기타 몇 가지 사항에 영향을줍니다. 아니요개체의 컨텍스트를 변경합니다. 컨텍스트는 범위에있는 객체/ID를 정의합니다. 항목을 만든 후에 컨텍스트를 변경할 수 없습니다. 상위를 변경하면 컨텍스트가 변경 되더라도 너무 늦어서 개체가 만들어지고 ID/개체는 생성 단계에서만 조회됩니다.

해결 방법은 실제로 올바른 인수를 가진 QQmlComponent::create()으로 올바른 컨텍스트를 전달하는 것입니다. fillMeWithItemsContainer 컨텍스트로 항목을 만들어야하므로 포인터를 가져와 (이미 findChild으로 지정) 컨텍스트를 검색해야합니다 (QQmlEngine::contextForObject()). 그렇게하면 어떻게 작동시키는 지 알 수있을 것입니다.

세르게이에 동의하지만 JavaScript로 동적으로 개체를 만드는 것이 더 좋습니다. C++에서 QML을 변경하는 것은 레이어링 위반입니다. C++에서 QML에 액세스해서는 안되며, UI와 프로그램 로직을 더 잘 구분할 수 있어야합니다.

1

QML 엔진은 QObject*으로 캐스팅되었으므로 DynamicItem 인스턴스를 비 그래픽 항목으로 취급합니다.따라서 렌더링되지 않습니다. 렌더링하려면 적어도 QQuickItem*이어야합니다.

parent 속성은 부모 QQuickItem을 나타내며 QObject 부모와 같을 수 없으므로 setParent()과 동일한 문제가 발생할 것으로 생각됩니다.

두 질문 :

  1. 가 왜 JS 동적 객체를 생성하지 않을까요?
  2. 절대 fillMeWithItemsContainer 대신 상대 parent을 사용할 수 있습니까?

p.s. 나는 이것이 QML을 사용하는 다소 불규칙한 방식이며 그러한 해킹 된 접근에 대한 강한 이유가 있음을 당신이 알고 있다고 가정합니다.

+0

캐스팅은 무의미합니다. QQmlComponent :: create()는 올바른 유형의 개체를 만듭니다.이 개체는 QQuickItem의 하위 클래스입니다. 이 포인터를 캐스팅하면 어떤 식 으로든 타입이 변경되지 않고 QQuickItem을 유지합니다. –

+0

@tmcguire 수정 해 주셔서 감사합니다. 이 경우 DynamicObject 인스턴스 포인터를 QObject로 캐스팅하는 것은 적합하지 않습니다. (나는 컨텍스트 속성을 엉망으로 만들었다.) –