В моем приложении QML я пытаюсь создать сетку элементов, которые можно перевернуть одним нажатием кнопки. Задняя сторона такого предмета должна занимать большую часть экрана, пока он не будет перевернут назад.
Скажем, я начинаю со следующего представления моего приложения
Когда я нажимаю кнопку со знаком вопроса элемента в центре, элемент переворачивается и слегка перемещается. Что я ожидал увидеть после этого, так это следующее
Синяя коробка — это обратная сторона моего предмета, и она занимает большую часть экрана. Нажатие кнопки «X» в правом верхнем углу снова перевернет элемент обратно.
Однако то, что я на самом деле вижу после первого перелистывания, это следующее
Вы можете видеть, что части элементов в моей сетке покрыты моим перевернутым элементом, а части — нет.
Код, который я использую, выглядит следующим образом
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
Window {
id: main
width: 640
height: 480
visible: true
title: qsTr("Hello World")
function absolutePos(item) {
var my_x = item.x
var my_y = item.y
if (item.parent !== null) {
var parent_pos = absolutePos(item.parent)
my_x += parent_pos.x
my_y += parent_pos.y
}
return {x: my_x, y: my_y}
}
GridLayout {
columns: 5; rows: 3
Repeater {
model: 15
delegate: Item {
width: main.width / 5 - 10
height: main.height / 3 - 10
Flipable {
id: flipable
anchors.fill: parent
property bool flipped: false
front: Rectangle {
anchors.fill: parent
border.color: "black"
border.width: 2
}
back: Rectangle {
id: backSide
width: 580; height: 400
property var absolute_pos: absolutePos(this)
border.color: "blue"
border.width: 2
Button {
anchors.top: parent.top
anchors.right: parent.right
text: "X"
width: 30; height: 30
onClicked: {
flipable.flipped = !flipable.flipped
}
}
}
transform: [
Rotation {
id: rotation
origin.x: flipable.width / 2
origin.y: flipable.height / 2
axis.x: 0; axis.y: 1; axis.z: 0
angle: 0
},
Translate {
id: translation
x: 0; y: 0
}
]
states: State {
name: "back"
PropertyChanges {
target: rotation
angle: 180
}
PropertyChanges {
target: translation
x: 490 - backSide.absolute_pos.x
}
PropertyChanges {
target: translation
y: 40 - backSide.absolute_pos.y
}
when: flipable.flipped
}
transitions: Transition {
ParallelAnimation {
NumberAnimation {
target: rotation
property: "angle"; duration: 300
}
NumberAnimation {
target: translation
property: "x"; duration: 300
}
NumberAnimation {
target: translation
property: "y"; duration: 300
}
}
}
}
Button {
anchors.top: parent.top
anchors.right: parent.right
text: "?"
width: 30; height: 30
onClicked: {
flipable.flipped = !flipable.flipped
}
}
}
}
}
}
Я уже пытался добиться эффекта, вручную установив parent
моего Flipable
на Window.contentItem
, чтобы он всегда был выше любых других предметов. Однако это также не устраняет проблему, поскольку элемент по-прежнему будет охватывать братьев и сестер, следующих за текущим элементом.
Также я все еще надеюсь, что есть решение, которое не требует манипулирования z-порядком моих предметов каким-то загадочным образом.
Я не уверен, что вы подразумеваете под «каким-то тайным способом», но изменение свойства z
вашего делегата совершенно нормально:
delegate: Item {
z: flipable.flipped ? 1 : 0
// ...
}
Вы также, вероятно, захотите скрыть "?" кнопка при переворачивании:
visible: !flipable.flipped
Ого, это так просто! Я боялся, что мне понадобится какая-то сложная арифметика z-порядка и/или даже некоторые функции, которые будут вызываться каждый раз, когда элемент переворачивается. Мне очень нравится это решение.