I am trying to move an item in my QML off-screen using a transition with AnchorChanges, like so:
Item {
id: view
Repeater {
id: repeater
model: 1
Rectangle {
id: card
property int index
color: "red"
radius: 10
width: parent.width * 0.9
height: parent.height * 0.7
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: units.gu(8)
states: [
State {
name: "hidden"
AnchorChanges { target: card; anchors.top: view.bottom }
}
]
transitions: Transition {
AnchorAnimation { duration: 5000 }
}
Component.onCompleted: card.state = "hidden"
}
}
}
I am using a Repeater because there will be several cards, which I want to move off-screen.
However, when I use the Repeater as shown above, there will be no animation. Instead, after a delay of 5 seconds, the card will be instantly hidden.
If I instead remove the repeater, the animation will be shown:
Item {
id: view
Rectangle {
id: card
property int index
color: "red"
radius: 10
width: parent.width * 0.9
height: parent.height * 0.7
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: units.gu(8)
states: [
State {
name: "hidden"
AnchorChanges { target: card; anchors.top: view.bottom }
}
]
transitions: Transition {
AnchorAnimation { duration: 5000 }
}
Component.onCompleted: card.state = "hidden"
}
}
Whats the reason for this?
Related
In my QML application I'm trying to create a grid of items that can be flipped at the press of a button. The backside of such an item should then fill a major part of the screen until it is flipped back.
Let's say I start off with the following view of my application
When I press the question mark button of the item in the center then the item is flipped and moved slightly. What I would expect to see after this is the following
The blue box is the backside of my item and it covers most of the screen. Pressing the 'X'-Button on the top right would again flip the item back.
However what I actually see after flipping the first time is the following
You can see that parts of the items in my grid are covered by my flipped item and parts are not.
The code I'm using is as follows
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
}
}
}
}
}
}
I was already trying to achieve the effect by manually setting the parent of my Flipable to Window.contentItem so that it will always be above any other items. However this also doesn't fix the problem since the item will still cover the siblings following the current item.
Also I'm still hoping, there is a solution which doesn't require manipulating the z-order of my items in some arcane way.
I am not sure what you mean by "some arcane way", but changing the z property of your delegate is perfectly fine:
delegate: Item {
z: flipable.flipped ? 1 : 0
// ...
}
You will also probably want to hide the "?" button when flipped:
visible: !flipable.flipped
I am trying to drag and drop a ListView row and I am having trouble at the drag stage. Below code doesn't drag anything and name column is not aligned properly. I don't want to specify a size for ListView and I want it to get its size from its content Row with id row. It should be able to because text has size coming from its font size and Rectangle has set width. ListView can get wider as needed to show the name part.
import QtQuick 2.11
import QtQuick.Layouts 1.11
ListView {
id: root
height: scrollview.viewport.height
model: listModel
delegate: dragDelegate
Component {
id: dragDelegate
MouseArea {
id: dragArea
anchors { left: parent.left; right: parent.right }
height: content.height
drag.target: pressed ? content : undefined
drag.axis: Drag.XAndYAxis
Rectangle {
id: content
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
height: row.implicitHeight
border.width: 1
border.color: "lightsteelblue"
color: "green"
radius: 2
states: State {
when: dragArea.pressed
ParentChange { target: content; parent: root }
AnchorChanges {
target: content
anchors { horizontalCenter: undefined; verticalCenter: undefined }
}
}
Row {
id: row
Text {
text: name
font.pointSize: 15
}
Rectangle {
height: parent.height
width: 40
color: hexColor
}
}
}
}
}
ListModel {
id: listModel
ListElement {
name: "first-name"
hexColor: "red"
}
ListElement {
name: "second-name"
hexColor: "green"
}
}
}
I am currently building a multi-user calendar app in Qt, and intend to use firebase realtime database to handle the user data and scheduled tasks.
Each user can login to the app and select days which, once clicking on a 'save' button, will be locked to their name. I have no previous experience with firebase and would like some help to begin structuring the database, I want to be able to separate users into departments also.
Below is the code of my calendar page on my app, what would I put into firebase to be able to connect the two?
any help would be much appreciated!!
Page {
title: "Calendar"
rightBarItem: NavigationBarItem {
contentWidth: saveButton.width
AppButton {
id: saveButton
text: "Save & Request"
anchors.right: parent.right
}
}
SystemPalette {
id: systemPalette
}
Flow {
id: row
anchors.fill: parent
spacing: 10
layoutDirection: "RightToLeft"
Calendar {
id: calendar
width: (parent.width > parent.height ? parent.width * 0.6 - parent.spacing : parent.width)
height: (parent.height > parent.width ? parent.height * 0.6 - parent.spacing : parent.height)
selectedDate: new Date()
focus: true
style: CalendarStyle {
dayDelegate: Item {
readonly property color sameMonthDateTextColor: "#444"
readonly property color selectedDateColor: Qt.platformos === "osx" ? "#3778d0" : systemPalette.highlight
readonly property color selectedDateTextColor: "white"
readonly property color differentMonthDateTextColor: "#bbb"
readonly property color invalidDatecolor: "#dddddd"
Rectangle {
anchors.fill: parent
border.color: "#00000000"
color: styleData.date !== undefined && styleData.selected? selectedDateColor : "#00000000"
anchors.margins: styleData.selected ? -1 : 0
}
Label {
id: dayDelegateText
text: styleData.date.getDate()
anchors.centerIn: parent
color: {
var color = invalidDatecolor;
if (styleData.valid) {
color = styleData.visibleMonth ? sameMonthDateTextColor : differentMonthDateTextColor ;
if (styleData.selected) {
color = selectedDateTextColor;
}
}
color ;
}
}
}
}
}
Component {
id: eventListHeader
Row {
id: eventDateRow
width: parent.width
height: eventDayLabel.height
spacing: 10
Label {
id: eventDayLabel
text: calendar.selectedDate.getDate()
font.pointSize: 35
}
Column {
height: eventDayLabel.height
Label {
readonly property var options: { weekday: "long" }
text: Qt.locale().standaloneDayName(calendar.selectedDate.getDay(), Locale.LongFormat)
font.pointSize: 18
}
Label {
text: Qt.locale().standaloneMonthName(calendar.selectedDate.getMonth())
+ calendar.selectedDate.toLocaleDateString(Qt.locale(), " yyyy")
font.pointSize: 12
}
}
}
}
Rectangle {
width: (parent.width > parent.height ? parent.width * 0.4 - parent.spacing : parent.width)
height: (parent.height > parent.width ? parent.height * 0.4 - parent.spacing : parent.height)
ListView {
id:eventListView
spacing: 4
clip: true
header: eventListHeader
anchors.fill: parent
anchors.margins: 10
model: eventModel.eventsForDate(calendar.selectedDate)
delegate: Rectangle {
width: eventListView.width
height: eventItemColumn.height
anchors.horizontalCenter: parent.horizontalCenter
Image {
anchors.top: parent.top
anchors.topMargin: 4
width: 12
height: width
source: "qrc:/images/eventindicator.png"
}
Rectangle {
width: parent.width
height: 1
color: "#eee"
}
Column {
id: eventItemColumn
anchors.left: parent.left
anchors.leftMargin: 20
anchors.right: parent.right
height: timeLabel.height + nameLabel.height + 8
Label {
id: nameLabel
width: parent.width
wrapMode: Text.Wrap
text: modelData.name
}
Label {
id: timeLabel
width: parent.width
wrapMode: Text.Wrap
text: modelData.startDate.toLocaleTimeString(calendar.locale, Locale.ShortFormat)
color: "#aaa"
}
}
}
}
}
}
}
If I understood correctly, you have not yet integrated Firebase to your Qt project?
You can have a look at this plugin for using Firebase with Qt Quick: https://v-play.net/doc/plugin-firebase/
Then you can listen to the reatimeValueChanged signal and update your calendar accordingly.
I am a beginer and i am not getting how to call canvas.requestPaint() in My QML ,Code is below:
//myTab.qml
TabView {
id: tv
width: parent.width
height: parent.height
antialiasing: true
style: TabViewStyle {
frameOverlap: -1
tab: Rectangle {
color: "Transparent"
implicitWidth: text1.width + 50
implicitHeight: 20
radius: 2
smooth: true
Canvas {
id: canvas1
anchors.fill: parent
width: parent.width
height: parent.height
onPaint: {
styleData.selected ? drawTab(canvas1,"#0C3142") :
drawTab(canvas1,"Transparent") //Some custom JS function to draw a object
}
Text {
id: text1
height: parent.height
verticalAlignment: Text.AlignVCenter
anchors.left : parent.left
anchors.leftMargin: 15
text: styleData.title
color: "white"
}
}
}
frame: Rectangle {
width: parent.width
height: parent.height
color: "Transparent"
border.color:"white"
}
tabBar: Rectangle {
color: "Transparent"
anchors.fill: parent
}
}
Tab {
id: tab1
title: "Tab1"
}
Tab{
id: tab2
title: "Tab2"
}
onCurrentIndexChanged: {
console.log("index changed "+currentIndex)
canvas1.repaint() //ERRROR - not defind canvas1
}
}
When i try to use in onCurrentIndexChanged, I am getting the following error:
ReferenceError: canvas1 is not defined.
Please Suggest.
You have the id canvas1 in another scope, as the tab-style is a Component and the ID therefore not necessarily unique for the TabView. It might be instantiated multiple times.
I have little experience with the TabView, so there might be another solution. I however would declare a signal: refresh in the TabView which I trigger, whenever I want to repaint.
Then I'd use a Connections-element within the Canvas to connect to this signal to execute the repaint
Example:
TabView {
id: tv
width: parent.width
height: parent.height
antialiasing: true
signal refresh // *** DEFINE SIGNAL HERE
style: TabViewStyle {
frameOverlap: -1
tab: Rectangle {
color: "Transparent"
implicitWidth: text1.width + 50
implicitHeight: 20
radius: 2
smooth: true
Canvas {
id: canvas1
anchors.fill: parent
width: parent.width
height: parent.height
onPaint: {
styleData.selected ? drawTab(canvas1,"#0C3142") :
drawTab(canvas1,"Transparent") //Some custom JS function to draw a object
}
function drawTab() { // *** I DONT KNOW WHAT SHOULD BE DONE HERE
console.log('do nothing')
}
// *** CONNECT TO SIGNAL HERE ***
Connections {
target: tv
onRefresh: canvas1.requestPaint() // *** repaint is not a function.
}
Text {
id: text1
height: parent.height
verticalAlignment: Text.AlignVCenter
anchors.left : parent.left
anchors.leftMargin: 15
text: styleData.title
color: "white"
}
}
}
frame: Rectangle {
width: parent.width
height: parent.height
color: "Transparent"
border.color:"white"
}
tabBar: Rectangle {
color: "Transparent"
anchors.fill: parent
}
}
Tab {
id: tab1
title: "Tab1"
}
Tab{
id: tab2
title: "Tab2"
}
onCurrentIndexChanged: {
console.log("index changed "+currentIndex)
refresh() // *** INVOKE SIGNAL HERE
}
}
My question is kind of a two part conditional question. I have a desktop application I'm writing in C++/Qt. In the app I have a couple lists that I want to decorate and add list items with icons and rich text.
I first attempted to do this with the QWidget world but the more I looked into it, the more I thought QML might be a better option. But now I'm wondering about that as well since it seems that QML Is more geared toward touch screen devices. Not to mention that my progress with QML has been frusating. Give them QML below, I cannot figure out how to: (1) get an item to highlight when I click it and (2) add a scroll bar:
import QtQuick 1.0
Item
{
width: 300
height: 200
ListModel
{
id: myModel2
ListElement { text: "List Item 1" }
ListElement { text: "List Item 2" }
ListElement { text: "List Item 3" }
ListElement { text: "List Item 4" }
ListElement { text: "List Item 5" }
ListElement { text: "List Item 6" }
}
Component
{
id: beerDelegate
Rectangle
{
id: beerDelegateRectangle
height: beerDelegateText.height * 1.5
width: parent.width
Text
{
id: beerDelegateText
text: "<b>" + modelData + "</b> <i>(" + modelData + ")</i>"
}
MouseArea
{
anchors.fill: parent
onClicked:
{
console.log("clicked: " + modelData + " at index: " + index);
beerList.currentIndex = index;
}
}
}
}
ListView
{
id: beerList
anchors.fill: parent
model: myModel2
delegate: beerDelegate
highlightFollowsCurrentItem: true
highlight: Rectangle
{
width: parent.width
color: "red"
}
focus: true
}
}
How can I accomplish what I'm looking for given this QML? Or is using QML in a QWidget desktop app just a bad idea all around?
For the first question (highlight):
Your list actually draws the highlight, however, your item delegate overpaints this with a white rectangle! Just replace the rectangle with an item and it works:
Component
{
id: beerDelegate
Item
{
...
}
}
For the second question (scroll bars):
As far as I know, QML doesn't provide scroll bars out of the box. There is however the Qt Desktop Components project (git repository) which gives you access to most of the widgets in the QML world. Among them, there is a ScrollArea.
It is no longer necessary to implement the Scrollbars yourself. There is the ScrollView-Item since Qt 5.1. Simply surround a Flickable-Item (e.g. the ListView-Item you use, is also "Flickable") with the ScrollView-Item and you'll be fine:
ScrollView {
ListView {
id: beerList
anchors.fill: parent
model: myModel2
delegate: beerDelegate
highlightFollowsCurrentItem: true
highlight: Rectangle
{
width: parent.width
color: "red"
}
focus: true
}
}
For the second question. i.e Scroll-bar on ListView:
I have created code for scroll bar on ListView. It also can work on the GridView
ScrollBar.qml
import Qt 4.7
Item {
property variant target
width: 8
anchors.top: target.top
anchors.bottom: target.bottom
anchors.margins: 1
anchors.rightMargin: 2
anchors.bottomMargin: 2
anchors.right: target.right
visible: (track.height == slider.height) ? false : true
Image {
id: scrollPath
width: 2
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
source: "qrc:/resources/buttons/slider2.png"
}
Item {
anchors.fill: parent
Timer {
property int scrollAmount
id: timer
repeat: true
interval: 20
onTriggered: {
target.contentY = Math.max(0, Math.min(target.contentY + scrollAmount,
target.contentHeight - target.height));
}
}
Item {
id: track
anchors.top: parent.top
anchors.topMargin: 1
anchors.bottom: parent.bottom
width: parent.width
MouseArea {
anchors.fill: parent
onPressed: {
timer.scrollAmount = target.height * (mouseY < slider.y ? -1 : 1)
timer.running = true;
}
onReleased: {
timer.running = false;
}
}
Image {
id:slider
anchors.horizontalCenter: parent.horizontalCenter
source: "qrc:/resources/buttons/slider.png"
width: parent.width
height: Math.min(target.height / target.contentHeight * track.height, track.height) < 20 ? 20 : Math.min(target.height / target.contentHeight * track.height, track.height)
y: target.visibleArea.yPosition * track.height
MouseArea {
anchors.fill: parent
drag.target: parent
drag.axis: Drag.YAxis
drag.minimumY: 0
drag.maximumY: track.height - height
onPositionChanged: {
if (pressedButtons == Qt.LeftButton) {
target.contentY = slider.y * target.contentHeight / track.height;
}
}
}
}
}
}
}
And I used scroll bar item with ListView in MyListView.qml as:
MyListView.qml
ListView {
id: list
clip: true
anchors.margins: 5
anchors.fill: parent
model: 10
delegate: trackRowDelegate
interactive: contentHeight > height
}
ScrollBar {
id: verticalScrollBar
target: list
clip: true
}
This ScrollBar item can be used with GridView as
GridView {
id: grid
clip: true
anchors.margins: 5
anchors.fill: parent
cellWidth:100
cellHeight: 100
model: items
interactive: contentHeight > height
snapMode: GridView.SnapToRow
delegate: myDelegate
}
ScrollBar {
id: verticalScrollBar
target: grid
clip: true
visible: grid.interactive
}