2017-07-19 73 views
0

我想要Flow其中的對象從左到右添加,但每行對齊到右側。逆佈局流程順序

import QtQuick 2.0 
import QtQuick.Controls 2.0 
Flow { 
    width: 400 
    anchors.right: parent.right 
    spacing: 2 
    Repeater { 
     model: ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 
     delegate: Button { 
      text: modelData 
      width: (83 * (model.index + 1)) % 100 + 30 
     } 
    } 
} 

我有右對齊的Flow,但在它的行會一直在Flow的左邊緣開始。我可以設置

layoutDirection: Qt.RightToLeft 

它會將行對齊到右側,但是項目的順序也會顛倒。

如果我扭轉模型(在這個例子中可以通過調用reverse(),具有ListModel我需要倒車ProxyModela將到左側,但行是無序。

我怎麼能達到那樣的東西?

回答

1
import QtQuick 2.5 
import QtQuick.Controls 2.1 

ApplicationWindow { 
    id: root; 
    width: 640 
    height: 480 
    visible: true 

    Rectangle { 
     z: -1 
     color: "#80000000" 
     width: flow.width 
     height: flow.height 
     anchors.centerIn: flow 
    } 

    Flow { 
     id: flow 
     width: 400 
     anchors.right: parent.right 
     spacing: 2 

     Repeater { 
      id: repeater 
      property real remainingRowSpace: flow.width 
      property real indexOfFirstItemInLastRow: 0 

      model: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'] 
      delegate: Rectangle { 
       property real buttonWidth: (83 * (model.index + 1)) % 100 + 30 

       color: "#80000000" 
       width: buttonWidth 
       height: childrenRect.height 

       Button { 
        x: parent.width - width 
        text: modelData 
        width: parent.buttonWidth 
       } 
      } 

      onItemAdded: { 
       var spacing = parent.spacing 

       // Check if new row. 
       if (item.width > remainingRowSpace) { 
        // Increase width of first item push row right. 
        itemAt(indexOfFirstItemInLastRow).width += remainingRowSpace 
        // Reset available space 
        remainingRowSpace = parent.width 
        // Store index of item 
        indexOfFirstItemInLastRow = index 
        // Don't need to subtract spacing for the first item 
        spacing = 0 
       } 

       remainingRowSpace -= (item.width + spacing) 

       // Handle when no more rows will be created. 
       if (index === repeater.count - 1) { 
        itemAt(indexOfFirstItemInLastRow).width += remainingRowSpace 
       } 
      } 
     } 
    } 
} 

這不是一個非常通用的或動態的解決方案,但它的工作原理。

+0

這是一個不錯的解決方案,對於這種情況,創建後所有東西都保持靜態。如果模型發生變化,則需要重新佈置一切。項目大小的變化也需要重新計算一切。這仍然是一個不錯的解決方案。 – derM

0

這仍然是一個進展中的工作,但可能仍然是可用於某些人

正如託尼·克利夫頓的解決方案,它採用了Repeater和它的onItemAdded - 方法,但使用Qt.binding保持東西更多動態。 這不是優於託尼克利夫頓的解決方案和選擇可能取決於用例。

上升空間:

  • 動態向ReversedFlow

缺點的寬度的各個Item -width

  • 動態的變化:

    • 填充底部排第一。第一行可能不完全(對於某些usecases這可能會更好)

    兩種解決方案都無法正常工作,具有ListModel使用,新的條目正在insert()版時。這兩種解決方案都應該在模型完全更換後(例如JSArrays和modelChanged()的手動呼叫)。

    從某種意義上說,兩種解決方案都不是Flow s,因爲Repeater負責佈局,所以可以拋入任意對象。所以Repeater必須創建Item s。我沒有得到它與ObjectModel工作。擺脫直放站將是我最後的擔憂。

    Item { 
        id: root 
        visible: false 
        width: 400 
        height: (rep.count > 0 ? rep.itemAt(0).y * -1 : 0) 
        anchors.centerIn: parent 
        property real spacing: 5 
        Item { 
         anchors.bottom: parent.bottom 
         anchors.right: parent.right 
         anchors.left: parent.left 
         Repeater { 
          id: rep 
          model: ListModel { 
           id: bm 
           ListElement { text: "a" } 
           ListElement { text: "b" } 
           ListElement { text: "c" } 
           ListElement { text: "d" } 
           ListElement { text: "e" } 
           ListElement { text: "f" } 
           ListElement { text: "g" } 
           ListElement { text: "h" } 
           ListElement { text: "i" } 
          } 
    
          onItemAdded: { 
           console.log(index, item, itemAt(index - 1)) 
           item.anchors.right = Qt.binding(
              function() { 
               if (rep.count === index + 1) return parent.right 
               var neighbor = rep.itemAt(index + 1) 
               if (neighbor.x - item.width - root.spacing < 0) return parent.right 
               return rep.itemAt(index + 1).left 
              } 
              ) 
           item.anchors.bottom = Qt.binding(
              function() { 
               if (rep.count === index + 1) return parent.bottom 
    
               var neighbor = rep.itemAt(index + 1) 
               if (neighbor.x - item.width - root.spacing < 0) 
                return neighbor.top 
               return neighbor.bottom 
              } 
              ) 
           item.anchors.rightMargin = Qt.binding(
              function() { 
               return (item.anchors.right === parent.right ? 0 : root.spacing) 
              } 
              ) 
           item.anchors.bottomMargin = Qt.binding(
              function() { 
               return (item.anchors.bottom === rep.itemAt(index + 1).top ? root.spacing : 0) 
              } 
              ) 
    
          } 
          delegate: Button { 
           text: modelData 
           property int count: 0 
           width: (83 * (index + count + 1)) % 100 + 30 
           onClicked: { 
            count++ 
           } 
          } 
         } 
        } 
    
        Rectangle { 
         id: debug 
         anchors.fill: parent 
         color: 'transparent' 
         border.color: 'red' 
        } 
    } 
    

    的想法背後,是初始化錨綁定添加的對象時,我在那裏定位每個Item右側一方或它的繼任者,如果有足夠的空間。
    我還將Item的底部固定到它的後續底部,如果它位於他旁邊,或者位於頂部,如果它開始新行。如果它沒有繼任者,它將被錨定在父母的底部。
    後一個事實,使得這個奇怪的構造有兩個必要的圍繞Item。外層將真正包圍一切,並動態增長,但這不可能是一個,我錨定整個鏈條,因爲我固定在底部。如果我要更改height,具體取決於childrenRect.height,我將以具有奇怪效果的綁定循環結束,因爲項目的y值不會保持不變。最初它會起作用,但是當物品因尺寸變化而移動時,它會破裂。