2016-06-30 19 views
0

Ich brauche einige Elemente, die Pixel-perfekt sind, und andere, die in der Größe veränderbar sein sollten, also versuche ich, Layouts zu vermeiden, indem ich nur Anker verwende.Warum haben Elemente, die im ApplicationWindow verankert sind, eine Größe von Null?

Wenn ich ein Objekt mit einer festen Größe als "Haupt Leinwand" habe, kann ich alles Notwendige für meine Ziele mit der Verankerung tun. Es funktioniert jedoch nicht mit dem Hauptfenster. Wenn ich ein Element haben, das in das Hauptfenster verankert ist, wird seine Größe angegeben als Null

ApplicationWindow 
{ 
    id: mainWindow 
    width: 1024 
    height: 768 
    minimumWidth: 800 
    minimumHeight: 480 
    Component.onCompleted: { console.log("mainWindow width: " + width) } 

    Item 
    { 
     id: topLevelItem 
     anchors.fill: parent 
     Component.onCompleted: { console.log("topLevelItem width: " + width) } 
    } 
} 

Interessanterweise wird die Breite des topLevelItem als 0 gedruckt, während die Breite des mainWindow korrekt als 1024 gedruckt wird.

fügte ich einige Elemente, und jetzt wird es seltsam:

ApplicationWindow 
{ 
    id: mainWindow 
    width: 1024 
    height: 768 
    minimumWidth: 800 
    minimumHeight: 480 
    Component.onCompleted: { console.log("mainWindow width: " + width) } 

    Item 
    { 
     id: topLevelItem 
     anchors.fill: parent 
     Component.onCompleted: { console.log("topLevelItem width: " + width) } 

     Rectangle 
     { 
      id: red 
      anchors.top: parent.top 
      anchors.bottom: parent.bottom 
      anchors.left: parent.left 

      width: 100 
      color: "#FF0000" 

      Component.onCompleted: { console.log("red width: " + width) } 
     } 


     Rectangle 
     { 
      id: green 

      anchors.top: parent.top 
      anchors.bottom: parent.bottom 
      anchors.left: red.right 
      anchors.right: blue.left 

      color: "#00FF00" 

      Component.onCompleted: { console.log("green width: " + width) } 
     } 

     Rectangle 
     { 
      id: blue 

      anchors.top: parent.top 
      anchors.bottom: parent.bottom 
      anchors.right: parent.right 

      width: 50 
      color: "#0000FF" 

      Component.onCompleted: { console.log("blue width: " + width) } 
     } 

    } 

} 

Alles angezeigt wird, wie es sein sollte. Auf der linken Seite befindet sich ein vertikaler roter Balken von 100 px, am rechten Rand ein vertikaler blauer Balken von 50 px und der Rest ist grün.

Was überrascht, ist, dass die Größen sind falsch:

qml: topLevelItem width: 0 
qml: blue width: 50 
qml: green width: -150 
qml: red width: 100 
qml: mainWindow width: 1024 

Die Höhe alles, mit Ausnahme von mainWindow, wird als Null gemeldet.

Ich brauche Zugriff auf die Größen, insbesondere auf die Größe des mittleren Bereichs, da es abhängig vom verfügbaren Platz beeinflussen muss, welche Art von anderen Elementen platziert werden.

Was kann die Ursache für dieses seltsame Verhalten sein, und habe ich etwas falsch gemacht? Wie kann ich korrekt auf die Größe des mittleren Rechtecks ​​zugreifen?

Antwort

2

QML ist eine deklarative Sprache, was bedeutet, dass Sie sich dagegen wehren können, wenn Sie versuchen, sich zu sehr auf die Reihenfolge der Bewertung bestimmter Dinge zu verlassen. Wenn Sie aus dem width von topLevelItem drucken, wie sie sich ändert, werden Sie sehen, dass es schließlich richtig ist:

import QtQuick 2.7 
import QtQuick.Controls 1.0 

ApplicationWindow { 
    id: mainWindow 
    width: 1024 
    height: 768 
    minimumWidth: 800 
    minimumHeight: 480 
    visible: true 

    Component.onCompleted: console.log("mainWindow width: " + width) 

    Item { 
     id: topLevelItem 
     anchors.fill: parent 
     onWidthChanged: print("topLevelItem width: " + width) 
     Component.onCompleted: console.log("topLevelItem width: " + width) 
    } 
} 

Ausgang:

qml: topLevelItem width: 0 
qml: mainWindow width: 1024 
qml: topLevelItem width: 1024 

Ich bin nicht sicher, was genau passiert, aber es ist wahrscheinlich, dass das Fenster zuerst seine Größe erhält und dann dem contentItem sagt, dass es anfangen kann, seine Einzelteile auszulegen und ihnen Größen zu geben. Dies geschieht asynchron und ist einer der Gründe, warum in einigen Fällen nicht auf den Imperativ-Code zurückgegriffen werden sollte.

Es ist auch Wert darauf hinzuweisen, dass Sie sowohl pixelgenaue Objekte als auch größenveränderbare Objekte verwenden können, wenn Sie Layouts verwenden. verwenden z.B. Layout.minimumWidth und Layout.maximumWidth bestimmte Größen zu erzwingen.

+0

Ich wusste, dass es keine strenge Reihenfolge der Auswertung gab, die die Reihenfolge der Deklaration respektieren würde, aber ich dachte, 'onCompleted' wird nur aufgerufen, nachdem das Element vollständig gerendert wurde. Es scheint, das war mein Fehler. – vsz