Drag and Drop within a GridView: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
(Fix code blocks formating) |
||
(3 intermediate revisions by 3 users not shown) | |||
Line 15: | Line 15: | ||
'''WidgetModel.qml''' | '''WidgetModel.qml''' | ||
< | <syntaxhighlight lang="qml"> | ||
import QtQuick 1.0 | |||
ListModel { | ListModel { | ||
ListElement { icon: "Images/widget1.png"; gridId: 0} | ListElement { icon: "Images/widget1.png"; gridId: 0} | ||
Line 27: | Line 28: | ||
ListElement { icon: "Images/widget9.png"; gridId: 8} | ListElement { icon: "Images/widget9.png"; gridId: 8} | ||
} | } | ||
</ | </syntaxhighlight> | ||
'''IconItem.qml''' | '''IconItem.qml''' | ||
< | <syntaxhighlight lang="qml"> | ||
Component | import QtQuick 2.0 | ||
Item | |||
id: main | Component { | ||
width: grid.cellWidth; height: grid.cellHeight | Item { | ||
Image | id: main | ||
id: item; parent: loc | width: grid.cellWidth; height: grid.cellHeight | ||
x: main.x + 5; y: main.y + 5 | |||
width: main.width - 10; height: main.height - 10; | Image { | ||
fillMode: Image.PreserveAspectFit; smooth: true | id: item; parent: loc | ||
source: icon | x: main.x + 5; y: main.y + 5 | ||
Rectangle { | width: main.width - 10; height: main.height - 10; | ||
anchors.fill: parent; | fillMode: Image.PreserveAspectFit; smooth: true | ||
border.color: "#326487"; border.width: 6 | source: icon | ||
color: "transparent"; radius: 5 | |||
visible: item.state | Rectangle { | ||
Behavior on x { enabled: item.state != "active" | anchors.fill: parent; | ||
} | border.color: "#326487"; border.width: 6 | ||
Behavior on y { enabled: item.state != "active" | color: "transparent"; radius: 5 | ||
} | visible: item.state = "active" | ||
SequentialAnimation on rotation {NumberAnimation { to: 2; duration: 60 } | } | ||
NumberAnimation { to: -2; duration: 120 } | |||
NumberAnimation { to: 0; duration: 60 } | Behavior on x { | ||
running: loc.currentId != -1 && item.state != "active"loops: Animation.Infinite; alwaysRunToEnd: true} | enabled: item.state != "active" | ||
states: State {name: "active"; when: loc.currentId | NumberAnimation { duration: 400; easing.type: Easing.OutBack } | ||
PropertyChanges { target: item; x: loc.mouseX - width/2; y: loc.mouseY - height/2; scale: 0.5; z: 10 } | } | ||
} | |||
transitions: Transition { NumberAnimation { property: "scale"; duration: 200} } | Behavior on y { | ||
} | enabled: item.state != "active" | ||
} | NumberAnimation { duration: 400; easing.type: Easing.OutBack } | ||
} | } | ||
</ | |||
SequentialAnimation on rotation { | |||
NumberAnimation { to: 2; duration: 60 } | |||
NumberAnimation { to: -2; duration: 120 } | |||
NumberAnimation { to: 0; duration: 60 } | |||
running: loc.currentId !== -1 && item.state !== "active" | |||
loops: Animation.Infinite; alwaysRunToEnd: true | |||
} | |||
states: State { | |||
name: "active"; when: loc.currentId === gridId | |||
PropertyChanges { target: item; x: loc.mouseX - width/2; y: loc.mouseY - height/2; scale: 0.5; z: 10 } | |||
} | |||
transitions: Transition { NumberAnimation { property: "scale"; duration: 200} } | |||
} //Image | |||
} //Item | |||
} //Component | |||
</syntaxhighlight> | |||
'''Main.qml''' | '''Main.qml''' | ||
< | <syntaxhighlight lang="qml"> | ||
import QtQuick | import QtQuick 2.0 | ||
import QtQuick.Controls 2.2 | |||
width: 640; height: 480 | |||
color: "#222222" | ApplicationWindow { | ||
GridView { | width: 640; height: 480 | ||
id: grid | color: "#222222" | ||
interactive: false | visible: true | ||
anchors | |||
topMargin: 60 | GridView { | ||
leftMargin: 140 | id: grid | ||
interactive: false | |||
anchors.fill: parent | |||
cellWidth: 120 | topMargin: 60 | ||
model: WidgetModel { id: icons } | bottomMargin: 60 | ||
delegate: IconItem { } | leftMargin: 140 | ||
MouseArea { | rightMargin: 140 | ||
property int currentId: | |||
property int newIndex // Current Position in model | cellWidth: 120 | ||
property int index: grid.indexAt(mouseX, mouseY) // Item underneath cursor | cellHeight: 120 | ||
id: loc | model: WidgetModel { id: icons } | ||
anchors.fill: parent | delegate: IconItem { } | ||
onPressAndHold: currentId = icons.get(newIndex = index).gridId | } | ||
onReleased: currentId = | |||
MouseArea { | |||
if (loc | property int currentId: -1 // Original position in model | ||
icons.move(newIndex, newIndex = index, 1) | property int newIndex // Current Position in model | ||
} | property int index: grid.indexAt(mouseX, mouseY) // Item underneath cursor | ||
id: loc | |||
anchors.fill: parent | |||
onPressAndHold: currentId = icons.get(newIndex = index).gridId | |||
onReleased: currentId = -1 | |||
onPositionChanged: { | |||
if (loc !== currentId && index !== -1 && index !== newIndex) | |||
icons.move(newIndex, newIndex = index, 1) | |||
} | |||
} | |||
} | } | ||
</ | </syntaxhighlight> | ||
Latest revision as of 21:52, 12 April 2023
This wiki entry is created in response to a few forum threads (links at bottom) asking for this method. Feel free to contribute to this article with explanations or code.
Drag and Drop within a GridView
This example will demonstrate the iOS style (video here ) of dragging and dropping ListModel elements within a GridView.
There are three files in this example. One for the model (WidgetModel.qml), one for the delegate (IconItem.qml) and one for the GridView (Main.qml).
WidgetModel.qml
import QtQuick 1.0
ListModel {
ListElement { icon: "Images/widget1.png"; gridId: 0}
ListElement { icon: "Images/widget2.png"; gridId: 1}
ListElement { icon: "Images/widget3.png"; gridId: 2}
ListElement { icon: "Images/widget4.png"; gridId: 3}
ListElement { icon: "Images/widget5.png"; gridId: 4}
ListElement { icon: "Images/widget6.png"; gridId: 5}
ListElement { icon: "Images/widget7.png"; gridId: 6}
ListElement { icon: "Images/widget8.png"; gridId: 7}
ListElement { icon: "Images/widget9.png"; gridId: 8}
}
IconItem.qml
import QtQuick 2.0
Component {
Item {
id: main
width: grid.cellWidth; height: grid.cellHeight
Image {
id: item; parent: loc
x: main.x + 5; y: main.y + 5
width: main.width - 10; height: main.height - 10;
fillMode: Image.PreserveAspectFit; smooth: true
source: icon
Rectangle {
anchors.fill: parent;
border.color: "#326487"; border.width: 6
color: "transparent"; radius: 5
visible: item.state = "active"
}
Behavior on x {
enabled: item.state != "active"
NumberAnimation { duration: 400; easing.type: Easing.OutBack }
}
Behavior on y {
enabled: item.state != "active"
NumberAnimation { duration: 400; easing.type: Easing.OutBack }
}
SequentialAnimation on rotation {
NumberAnimation { to: 2; duration: 60 }
NumberAnimation { to: -2; duration: 120 }
NumberAnimation { to: 0; duration: 60 }
running: loc.currentId !== -1 && item.state !== "active"
loops: Animation.Infinite; alwaysRunToEnd: true
}
states: State {
name: "active"; when: loc.currentId === gridId
PropertyChanges { target: item; x: loc.mouseX - width/2; y: loc.mouseY - height/2; scale: 0.5; z: 10 }
}
transitions: Transition { NumberAnimation { property: "scale"; duration: 200} }
} //Image
} //Item
} //Component
Main.qml
import QtQuick 2.0
import QtQuick.Controls 2.2
ApplicationWindow {
width: 640; height: 480
color: "#222222"
visible: true
GridView {
id: grid
interactive: false
anchors.fill: parent
topMargin: 60
bottomMargin: 60
leftMargin: 140
rightMargin: 140
cellWidth: 120
cellHeight: 120
model: WidgetModel { id: icons }
delegate: IconItem { }
}
MouseArea {
property int currentId: -1 // Original position in model
property int newIndex // Current Position in model
property int index: grid.indexAt(mouseX, mouseY) // Item underneath cursor
id: loc
anchors.fill: parent
onPressAndHold: currentId = icons.get(newIndex = index).gridId
onReleased: currentId = -1
onPositionChanged: {
if (loc !== currentId && index !== -1 && index !== newIndex)
icons.move(newIndex, newIndex = index, 1)
}
}
}
Relevant forum threads:
iOS Style Rearrange of Icons