How to animate a message that appears on bottom? - qt

I'm showing a message on the bottom:
Msg.qml
import QtQuick 2.4
Item {
property alias text: mf.text
anchors.fill: parent
antialiasing: false
opacity: 0.9
z: 100
MsgForm {
id: mf
width: parent.width
y: parent.height - height - 5
}
}
MsgForm.ui.qml
import QtQuick 2.4
Item {
property alias text: msg.text
width: 200
id: message
height: msg.height+10
Rectangle {
id: rectangle
color: "#fb9191"
anchors.fill: parent
border.color: "#fd6666"
border.width: 2
Text {
id: msg
anchors.top: parent.top
anchors.topMargin: 2
textFormat: Text.PlainText
anchors.right: parent.right
anchors.rightMargin: 4
anchors.left: parent.left
anchors.leftMargin: 4
wrapMode: Text.WordWrap
clip: false
font.bold: true
font.pointSize: 12
font.family: "Tahoma"
}
}
}
How can I animate the form to appear from the bottom smoothly?
After the animation, if the window resizes, the message must stay always on the bottom.

You can play with anchors.bottomMargin property to raise the message item from the bottom.
import QtQuick 2.4
Item {
property alias text: mf.text
anchors.fill: parent
antialiasing: false
opacity: 0.9
z: 100
MsgForm {
id: mf
property bool showing: false
width: parent.width
anchors{
bottom: parent.bottom
bottomMargin: mf.showing ? 0 : -mf.height
Behavior on bottomMargin{
NumberAnimation{ }
}
}
}
}

Thanks everyone. In the end I've solved the issue by following advices received in the qtcentre forum.
The desired effect can be achieved easily by defining a local numerical property that is use to bind to either an anchors.XXXXmargin or the y property expression.
Following this approach a possible solution is the following:
MsgForm {
property bool showing: false
property int position: showing ? height : 0
width: parent.width
y: parent.height - position
Behavior on position {
NumberAnimation {duration: 500}
}
}

You can make an animation on the opacity change:
Msg.qml
import QtQuick 2.4
Item {
property alias text: mf.text
anchors.fill: parent
antialiasing: false
opacity: 0.9
z: 100
MouseArea{
anchors.fill: parent
onClicked: mf.opacity = !mf.opacity
}
MsgForm {
id: mf
//y: parent.height - height - 5
opacity:0
Behavior on opacity {
NumberAnimation{
duration:600
}
}
width: parent.width
anchors.bottom: parent.bottom
}
}
or any other NumberAnimation. I recommand you to create States, within it do some propertyChanges, and on some actions, example button clicked change states.
example in your MsgForm.ui.qml add:
MouseArea{
anchors.fill: parent
onClicked: mf.state= "show"
}
and in the action, example:
in my mouseArea I change the state of mf
MouseArea{
anchors.fill: parent
onClicked: mf.state= "show"
}
If you want an Animation on the y try this:
MsgForm.ui.qml
import QtQuick 2.4
Item {
id: message
property alias text: msg.text
width: parent.width
height: msg.height+10
Rectangle {
id: rectangle
color: "#fb9191"
anchors.fill: parent
border.color: "#fd6666"
border.width: 2
Text {
id: msg
anchors.top: parent.top
anchors.topMargin: 2
textFormat: Text.PlainText
anchors.right: parent.right
anchors.rightMargin: 4
anchors.left: parent.left
anchors.leftMargin: 4
wrapMode: Text.WordWrap
clip: false
font.bold: true
font.pointSize: 12
font.family: "Tahoma"
}
}
Behavior on y {
NumberAnimation{
duration:300
}
}
states: [
State {
name: "show"
PropertyChanges {
target: message
y: parent.height - height
}
},
State {
name: "hide"
PropertyChanges {
target: message
y: parent.height + height + 5
}
}
]
}
Msg.qml
import QtQuick 2.4
Rectangle {
property alias text: mf.text
width:800
height: 480
antialiasing: false
opacity: 0.9
z: 100
MouseArea{
anchors.fill: parent
onClicked: mf.state= "show"
}
MsgForm {
id: mf
//y: parent.height - height - 5
y: parent.height +height + 5
width: parent.width
}
}

Related

QML - SpinBox - Data validation

I have the following SpinBox model which I am trying to recreate using the new QtQuick.Control 2, because this one it's using version 1. And I've encountered some problems which I am not sure how to solve.
On the validation side, I should not be able to write anything on the suffix side, just on the number part. Also I should not be allowed to remote the suffix from there while editing
My width should be fixed and I should not be allowed to write more than that.
My Code:
import QtQuick 2.6
import QtQuick.Controls 2
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
SpinBox {
id: root
property color borderColor: "red"
property string multipleValuesTooltip: ""
property color backgroundColor: "yellow"
property bool showTooltip: true
font.pointSize: 10
property int maximumValue: 50
property int minimumValue: 0
property string suffix: ""
property int decimals: 0
to: maximumValue
from: minimumValue
editable: true
rightPadding: {
console.log(root.contentItem.height)
return Math.max(40, Math.round(root.contentItem.height))
}
textFromValue: function(value, locale) {
return qsTr("%1"+suffix).arg(value);
}
contentItem: TextInput {
z: 5
text: root.textFromValue(root.value, root.locale)
font: root.font
color: "white"
selectionColor: "#21be2b"
selectedTextColor: "#ffffff"
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
validator: root.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
up.indicator: Rectangle {
height: parent.height / 2
anchors.right: parent.right
anchors.top: parent.top
implicitWidth: 20 // Adjust width here
implicitHeight: {
console.log(root.contentItem.height)
return root.contentItem.height - 10
}
color: root.up.pressed ? "red" : "pink"
Image {
source: "qrc:/resources/arrow-down.png"
height: Math.min(15, sourceSize.height)
width: Math.min(30, sourceSize.width)
anchors.centerIn: parent
rotation: 180
}
}
down.indicator: Rectangle {
height: parent.height / 2
anchors.right: parent.right
anchors.bottom: parent.bottom
implicitHeight: root.contentItem.height - 10
implicitWidth: {
console.log("W: ",root.width)
return 20
}
color: root.down.pressed ? "red" : "pink"
Image {
source: "qrc:/resources/arrow-down.png"
height: Math.min(15, sourceSize.height)
width: Math.min(30, sourceSize.width)
anchors.centerIn: parent
}
}
background: Item {
implicitHeight: root.height === 0 ? Math.max(30, Math.round(root.contentItem.height * 1.2)) : root.height
implicitWidth: root.contentItem.width + leftPadding +rightPadding
baselineOffset: root.anchors.baselineOffset
Rectangle {
id: baserect
anchors.fill: parent
color: "purple"
radius: 3
}
Rectangle { // Border only
anchors.fill: parent
border.color: "black"
color: "transparent"
radius: 3
}
Rectangle {
anchors.right: parent.right
anchors.rightMargin: root.rightPadding - 10
anchors.verticalCenter: parent.verticalCenter
color: "black"
height: parent.height - parent.height/5
width: 1
}
}
}
I couldn't find any documentation or any kind of information regarding this wherever I've searched for. If any of you could help me I would be really grateful.

QML ScrollBar combined with ListView

I'm new to QML and QT so don't blame me if this question is going to sound stupid for most of you but I've search all over the internet without any luck in founding an answer.
What I'm trying to do:
I'm having a ScrollView which has inside of it a ScrollBar and a ListView.
I want that at the moment when I'm scrolling the ListView elements to also move the bar from ScrollBar. In other words, I want to use the ScrollBar as an overall view of your current position, you are not supposed to touch that, its only purpose is for viewing.
My Code:
ScrollView{
implicitHeight: 100
implicitWidth: 50
anchors.fill: parent
ScrollBar.horizontal: ScrollBar{
id: hbar
active: true
policy: ScrollBar.AlwaysOn
anchors {
left: parent.left
top: parent.top
right: parent.right
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 50
opacity: enabled ? 1 : 0.3
color: hbar.down ? "#red" : "black"
}
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 100
radius: width / 2
color: hbar.pressed ? "#81e889" : "#c2f4c6"
}
}
ListView {
id: listViewParent
height: listViewID.height/10*6
contentHeight: height*2
contentWidth: width*2
clip: false
interactive: false
keyNavigationWraps: true
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
enabled: true
scale: 1
transformOrigin: Item.Center
anchors.verticalCenter: parent.verticalCenter
boundsBehavior: Flickable.DragAndOvershootBounds
flickableDirection: Flickable.HorizontalFlick
highlightMoveDuration: 0
cacheBuffer: 300
snapMode: ListView.SnapToItem
layoutDirection: Qt.LeftToRight
orientation: ListView.Vertical
model: 1
delegate:
ListView {
width: parent.width;
height: parent.height;
spacing: listViewID.width/8/9
model: MovieListModel {}
orientation: ListView.Horizontal
id: listid
delegate:
Rectangle {
property int recDynamicHeight: listViewID.height/10*6
property int recOriginalHeight: listViewID.height/10*6
property int recDynamiclWidth: listViewID.width/7
property int recOriginalWidth: listViewID.width/7
id: rectPer
width: recDynamiclWidth
height: recDynamicHeight
Image {
id: image1
anchors.fill: parent;
source: model.imgUrl
}
Text {
property bool isVisible: false
color: "#ffffff"
anchors.fill: parent
visible: textid.isVisible
id: textid
text: model.title
font.bold: true
horizontalAlignment: Text.AlignLeft
font.pixelSize: listViewID.width/8/9
topPadding: listViewID.width/8/9
leftPadding: listViewID.width/8/9
}
Text {
anchors.topMargin: listViewID.width/8/9
color: "#ffffff"
anchors.fill: parent
visible: textid.isVisible
id: yearId
text: model.year
horizontalAlignment: Text.AlignLeft
font.pixelSize: listViewID.width/8/9
topPadding: listViewID.width/8/9*2
leftPadding: listViewID.width/8/9
}
MouseArea {
anchors.fill: parent
onPressed: {
rectPer.recDynamicHeight = rectPer.recOriginalHeight;
rectPer.recDynamicHeight += rectPer.recOriginalHeight/10;
rectPer.recDynamiclWidth += rectPer.recOriginalWidth/10;
console.log(textid.isVisible);
textid.isVisible = true;
textid.visible = textid.isVisible;
console.log(sideButtonID.x);
console.log(sideButtonID.y);
console.log(model.year + " clicked");
}
onClicked: {
console.log("INDEX: " + model.id)
load_page(PageType.movie_detailed_view, model.title, model.description, model.imgUrl, model.type, model.year)
}
onReleased: {
rectPer.recDynamicHeight = rectPer.recOriginalHeight;
rectPer.recDynamiclWidth = rectPer.recOriginalWidth;
textid.isVisible = false;
textid.visible = textid.isVisible;
}
}
}
}
}
}
Layout:
You could try use a Flickable instead of a ScrollView and spawn a ListView there(delegates: Rectangles). Then, spawn the Scrollbar inside the ListView

QML ListView::contentWidth is wider than actual content

Trying to implement ListView's content scroll by clicking on a button. When scrolling towards the end of the view ListView's content does not stop at the end of the last picture it overscrolls. Below I provided the minimum working example as well as the preview what goes wrong. Just change the .img path to make it work on your PC. I was looking for some help in sources of ListView and its inherited parent Flickable but nothing that could help to resolve the problem. How to make it stop at the end of the last picture?
import QtQuick 2.14
import QtQuick.Window 2.14
Window {
visible: true
width: 1024
height: 300
Item {
id: root
anchors.fill: parent
property var imagesUrlModel: ["file:///C:/Users/mikha/OneDrive/Изображения/toyota.jpg",
"file:///C:/Users/mikha/OneDrive/Изображения/toyota.jpg"
]
property int _width: 0
Component {
id: imageDelegate
Image {
id: image
sourceSize.height: 300
source: modelData
fillMode: Image.Stretch
}
}
Rectangle {
id: leftButton
anchors.top: root.top
anchors.bottom: parent.bottom
anchors.topMargin: 15
anchors.leftMargin: 10
anchors.left: parent.left
color: "green"
width: 25
MouseArea {
anchors.fill: parent
onClicked: {
listView.contentX = listView.contentX > 0
? listView.contentX - 50 > 0 ? listView.contentX - 50 : 0
: 0
}
}
}
Rectangle {
id: rightButton
anchors.top: root.top
anchors.bottom: parent.bottom
anchors.topMargin: 15
anchors.rightMargin: 10
anchors.right: parent.right
color: "green"
width: 25
MouseArea {
anchors.fill: parent
onClicked: {
listView.contentX = listView.contentX < listView.contentWidth
? listView.contentX + 50
: listView.contentWidth
//wrong content width
}
}
}
ListView{
id: listView
clip: true
boundsBehavior: Flickable.StopAtBounds
anchors.topMargin: 15
anchors.left: leftButton.right
anchors.right: rightButton.left
anchors.top: root.top
anchors.bottom: parent.bottom
spacing: 5
orientation: ListView.Horizontal
model: root.imagesUrlModel
delegate: imageDelegate
}
}
}
In your example just change listView.contentWidth to listView.contentWidth-listView.width in onClicked event for rightButton. But that's not enough. You should check whether the listView.contentX+50 is not overflowing listView.contentWidth-listView.width before you update the listView.contentX. In such case you need to update listView.contentX with difference between listView.contentWidth and listView.width.
Here it is:
listView.contentX = listView.contentX+50 <= listView.contentWidth-listView.width
? listView.contentX + 50
: listView.contentWidth - listView.width
I used another approach with repeater and scrollview and it has worked!
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
Window {
visible: true
width: 1024
height: 300
Item {
id: contentItem
anchors.fill: parent
Rectangle {
id: rightButton
anchors.top: contentItem.top
anchors.bottom: contentItem.bottom
anchors.rightMargin: 10
anchors.right: contentItem.right
color: "green"
width: 25
MouseArea {
anchors.fill: parent
onClicked: {
var allowedWidth = scrollView.flickableItem.contentWidth - scrollView.viewport.width
if(row.width < scrollView.viewport.width){
return
}
var offset = scrollView.flickableItem.contentX + 50
if(offset <= allowedWidth){
scrollView.flickableItem.contentX += 50
}
else {
scrollView.flickableItem.contentX = allowedWidth
}
}
}
}
ScrollView {
id: scrollView
anchors.left: contentItem.left
anchors.right: rightButton.left
anchors.top: contentItem.top
anchors.bottom: contentItem.bottom
clip: true
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
property var imagesUrlModel: [
"file:///C:/Users/mikha/OneDrive/Изображения/toyota.jpg",
"file:///C:/Users/mikha/OneDrive/Изображения/toyota.jpg"
]
Row {
id: row
spacing: 15
Repeater {
id: repeater
anchors.left: parent.left
anchors.right: parent.right
model: scrollView.imagesUrlModel
delegate: Component {
id: imageDelegate
Image {
id: image
sourceSize.height: 300
source: modelData
fillMode: Image.Stretch
}
}
}
}
}
}
}

QML pieMenu on draggable object

I've got a draggable object that is created by a Javascript, which is working fine. But when I create a PieMenu inside it, the object isn't created/visible in the Javascript context:
import QtQuick 2.8
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
import QtQml.Models 2.2
Rectangle {
id: rev
width: 100
height: 80
color: "transparent"
antialiasing: false
Drag.active: dragArea.drag.active
MouseArea {
id: dragArea
width: parent.width
height: parent.height + 10 // easier to get
anchors.centerIn: parent
drag.target: parent
drag.axis: Drag.XAndYAxis
onClicked: pieMenu.popup(mouseX, mouseY), console.log("clicked")
}
PieMenu {
id: pieMenu
MenuItem {
text: "Add vertical bar"
onTriggered: print("Action 2")
}
}
Gauge {
id: revgauge
anchors.fill: parent
anchors.margins: 10
orientation : Qt.Horizontal
minorTickmarkCount: 4
tickmarkStepSize : 5000
minimumValue: 0
maximumValue: 10000
Behavior on value {
NumberAnimation {
duration: 5
}
}
Text {
font.pixelSize: (parent.height / 3)
anchors.top : parent.top
font.bold: true
font.family: "Eurostile"
color: "white"
anchors.horizontalCenter: parent.horizontalCenter
}
style: GaugeStyle {
valueBar: Rectangle {
implicitWidth: rev.height /3
color: Qt.rgba(revgauge.value / revgauge.maximumValue, 0, 1 - revgauge.value / revgauge.maximumValue, 1)
}
}
}
}
Can Mousearea handle dragging and a PieMenu at once? If not how can it be solved?
Consider QML PieMenu boundingItem. It addresses an exact issue with MouseArea you presented.

qt qml how can I create a list view feed item containing an icon and description?

I created an example. I do not know why I get a crash when I try to resize the window horizontally. Crash happens only when iconVisible is true
here is the qml code from the main, paste this in a hello world qt quick controls 2 project to test:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick.XmlListModel 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Page {
anchors.fill: parent
XmlListModel{
id : modelId
namespaceDeclarations: "declare namespace media = 'http://search.yahoo.com/mrss/';"
source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2&tags="
query: "//item[title and media:thumbnail and media:content]"
}
ListView {
anchors.fill: parent
model: modelId
Layout.fillWidth: true
delegate: itemDelegateId
ScrollBar.vertical: ScrollBar {}
}
Component {
id: itemDelegateId
Rectangle {
property bool iconVisible: true
property string contentText: "contentaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
property double itemHeight: 100
property int titleTextSize: 32
property int columnLayoutLeftMargin: (iconVisible)? 20 : 0
property string borderColor: "black"
property int iconSize: (iconVisible)? 40 : 0
height : itemHeight
anchors {
left: parent.left
right: parent.right
}
border.color: borderColor
border.width: 1
RowLayout {
anchors {
fill: parent
}
Rectangle {
id: notificationIconId
visible: iconVisible
anchors {
top: parent.top
}
height: iconSize
width: iconSize
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
}
}
ColumnLayout {
id: columnLayoutId
anchors {
top: parent.top
bottom: parent.bottom
left: notificationIconId.right
right: parent.right
}
Text {
id: contentId
anchors {
top: parent.top
bottom: parent.bottom
}
Layout.fillWidth: true
font.pixelSize: 20
elide: Text.ElideRight
maximumLineCount: 3
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
color: "black"
text: contentText
}
}
}
}
}
}
}
There are a few issues here. The first is that Layout.fillWidth: true has no effect, as Page is not a layout:
ListView {
anchors.fill: parent
model: modelId
Layout.fillWidth: true // remove
delegate: itemDelegateId
ScrollBar.vertical: ScrollBar {}
}
The second is that you shouldn't specify width and height for items in a layout:
Rectangle {
id: notificationIconId
visible: iconVisible
anchors {
top: parent.top
}
height: iconSize // Should be Layout.preferredHeight: iconSize
width: iconSize // Should be Layout.preferredWidth: iconSize
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
}
}
You can't use horizontal anchors on an item managed by a horizontal layout:
ColumnLayout {
id: columnLayoutId
anchors {
top: parent.top
bottom: parent.bottom
// This ColumnLayout is managed by a RowLayout, so these two lines have to go
left: notificationIconId.right
right: parent.right
}
}
Same thing for the Text item:
Text {
id: contentId
// Can't use vertical anchors on an item that is managed by a ColumnLayout
anchors {
top: parent.top
bottom: parent.bottom
}
Layout.fillWidth: true
font.pixelSize: 20
elide: Text.ElideRight
maximumLineCount: 3
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
color: "black"
text: contentText
}
With all of those issues fixed, it seems to work as expected:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick.XmlListModel 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Page {
anchors.fill: parent
XmlListModel{
id : modelId
namespaceDeclarations: "declare namespace media = 'http://search.yahoo.com/mrss/';"
source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2&tags="
query: "//item[title and media:thumbnail and media:content]"
}
ListView {
anchors.fill: parent
model: modelId
delegate: itemDelegateId
ScrollBar.vertical: ScrollBar {}
}
Component {
id: itemDelegateId
Rectangle {
property bool iconVisible: true
property string contentText: "contentaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
property double itemHeight: 100
property int titleTextSize: 32
property int columnLayoutLeftMargin: (iconVisible)? 20 : 0
property string borderColor: "black"
property int iconSize: (iconVisible)? 40 : 0
height : itemHeight
anchors {
left: parent.left
right: parent.right
}
border.color: borderColor
border.width: 1
RowLayout {
anchors {
fill: parent
}
Rectangle {
id: notificationIconId
visible: iconVisible
anchors {
top: parent.top
}
Layout.preferredHeight: iconSize
Layout.preferredWidth: iconSize
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
}
}
ColumnLayout {
id: columnLayoutId
anchors {
top: parent.top
bottom: parent.bottom
}
Text {
id: contentId
Layout.fillWidth: true
font.pixelSize: 20
elide: Text.ElideRight
maximumLineCount: 3
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
color: "black"
text: contentText
}
}
}
}
}
}
}

Resources