[SOLVED] QML Binding Loop For Width? Where?



  • I have a program utilizing a QML ListView consisting of Image delegates, which are hooked to a QAbstractListModel called a "snapshotsModel" behind the scenes. The snapshotsModel has two invokable functions called heightForWidth and widthForHeight. These simply return a value to maintain the aspect ratio. The ListView also has a signal handler for when the Qt dock containing it changes orientation. The point is that this list, and its images, change size and orientation according to the dock's orientation (vertically-scolling lists in horizontal docks look goofy). The signal itself comes from C++. The QML follows:

    @import QtQuick 1.1

    Rectangle
    {
    color: "#f0ebe2"

    Component
    {
    id: imageDelegate
    Image
    {
    function getHeight()
    {
    if (snapshotsView.orientationIsHorizontal)
    {
    return parent.height;
    }
    else
    {
    return snapshotsModel.heightForWidth(objectId, width);
    }
    }

         function getWidth()
         {
            if (snapshotsView.orientationIsHorizontal)
            {
               return snapshotsModel.widthForHeight(objectId, height);
            }
            else
            {
               return parent.width;
            }
         }
    
         height: getHeight()
         width: getWidth()
    
         // Qt bug 14900: No way to reload images. The random number is a hack to
         // force it.
         source: "image://snapshots/" + objectId + "_" + Math.floor(Math.random()*1001)
         smooth: true
         cache: false
    
         MouseArea
         {
            anchors.fill: parent
            onClicked:
            {
               // Do something here
               snapshotsView.currentIndex = index;
            }
         }
      }
    

    }

    ListView
    {
    property bool orientationIsHorizontal: false

      id: snapshotsView
      objectName: "SnapshotsList"
      anchors.fill: parent
      model: snapshotsModel
      delegate: imageDelegate
      spacing: 10
    
      // Signal handlers
      Connections
      {
         target: snapshotsModel
         onOrientationChanged:
         {
            snapshotsView.orientationIsHorizontal = isHorizontal;
    
            if (isHorizontal)
            {
               snapshotsView.orientation = ListView.Horizontal;
            }
            else
            {
               snapshotsView.orientation = ListView.Vertical;
            }
         }
      }
    

    }
    }
    @

    My question is this: Whenever the dock moves to the top or bottom (i.e. making the ListView go horizontal), I get a "QML QDeclarativeImage_QML_0: Binding loop detected for property 'width'" error. It works fine, but the error is annoying, and I don't see the loop. Does anyone else? Note that no error is produced when the dock is on the left or the right (i.e. the ListView is vertical).

    Thanks for any help!



  • You are setting the Image size with Image size....
    width = getWidth() = return parent.width == > LOOP ! "width" is not a variable! It's a property!
    And you cannot use invokable methode in this case. There is no signal to call it..! You should have something easier like this :

    @width : isHorizontal ? valueA : valueB
    height : isHorizontal ? valueB : valueA@
    where valueA and valueB are data from model .

    But I think, you are a beginner with QML property system and Model. Ask me a small exemple, I will do it for you .



  • Dridk, thanks for the response. First of all, I don't understand how a child's width dependent on its parent width causes a loop? The parent width doesn't depend on the child width, so where is the loop? Also, no loop is detected while child width = parent.width, it's when width depends on the height property. Can you please explain that a little more?

    As for invokable, I referred to this documentation: http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html#exchanging-data-between-qml-and-c . To quote: "To call a C++ function from QML, the function must be either a Qt slot, or a function marked with the Q_INVOKABLE macro, to be available to QML." It works fine, no signals needed.

    EDIT: I guess I assumed my parent.width in the Image was the Rectangle... but I guess it's actually the component. Is that what you mean? So if I used the ListView width instead, this would be okay?



  • Try using :
    sourceSize.width and sourceSize.height insteed.

    @snapshotsModel.widthForHeight(objectId, sourceSize.height)@



  • Did you look around PreserveAspectFit property ? It should be the best way for your problem



  • Dridk, sorry, I should have mentioned PreserveAspectFit for the fill mode. It works, but only until if the image is scaled smaller than its original size. I needed something that would also scale the image LARGER than its original size, pixelating as necessary. That's why I'm doing this widthForHeight/heightForWidth stuff in the first place.

    Also, sourceSize contains the actual image size, and I want to be able to scale, so that doesn't work.

    You did lead me to the solution though, thank you, and that was to add an ID to the rectangle and use ITS height and width. No more loop :) .


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.