PDA

View Full Version : Sliding effect of widgets created using QQuickWidget.



smrati.johri
7th March 2016, 19:04
hi all,

I have to achieve sliding effect on widgets. I have created two widget using QQuickWidget.
widget 1: is created using a static qml
widget 2 : is a dynamic widget created using javascript embedded in a qml.

now when I show/hide either of the widgets its behaving fine. but I want a sliding effect like widget 1 moves up and widget 2 slowing enters from below the window.
I am very new to QT started programming in this language last week itself. please help me I am a little stuck. I am using qt 5.5 on windows platform IDE : qtcreator 3.5.1

below are the topic I am referring to and trying to code to achieve my aim, but still unable to achieve my result
1. qt widget positioning
2. QPropertyAnimation (but to show/hid my widget I am using QTimer::singleShot)

code:


//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQuickView>
#include <QObject>
#include <QThread>
#include <QTimer>
#include <QPropertyAnimation>

MainWindow::MainWindow(QQuickWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mQQuickWidget = new QQuickWidget();
mQQuickWidget->setSource(QUrl("qrc:/qml/res/layouts/homescreen.qml"));
mQQuickWidget->rootContext()->setContextProperty("myModel", 500);
ui->verticalLayout->addWidget(mQQuickWidget);

QTimer::singleShot(2000, this, SLOT(addNewImage()));

}

void MainWindow ::addNewImage()
{

QQuickWidget *mQQuickWidget1 = new QQuickWidget();
mQQuickWidget1->setSource(QUrl("qrc:/qml/res/layouts/AndroidDelegate.qml"));
ui->verticalLayout->addWidget(mQQuickWidget1);

mQQuickWidget->hide();
}

MainWindow::~MainWindow()
{
delete ui;
}



//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QQuickItem>
#include <QQmlContext>
#include <QQuickWidget>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QQuickWidget *parent = 0);
~MainWindow();

public slots:
void addNewImage();

private:
Ui::MainWindow *ui;
QQuickWidget *mQQuickWidget;
};



//homescreen.qml

import QtQuick 2.0
import QtQml.Models 2.1
import "qrc:/componentCreation.js" as MyScript

Rectangle {
id: root
color: "lightgray"
width: 800
height: 480
property bool printDestruction: false

//! [0]
ObjectModel {
id: itemModel

Rectangle {
width: view.width; height: view.height
color: "#000000"
Text { text: "Page 1"; font.bold: true; anchors.centerIn: parent ;}

Image {
id: image1
width: 100
height: 100
x: myModel
y:100
fillMode: Image.PreserveAspectFit
smooth: true
source: "qrc:/images/res/images/navigation_next_item.png"


}
Component.onCompleted: MyScript.createSpriteObjects();

Component.onDestruction: if (printDestruction) print("destroyed 1")
}
Rectangle {
width: view.width; height: view.height
color: "#F0FFF7"
Text { text: "Page 2"; font.bold: true; anchors.centerIn: parent }

Component.onDestruction: if (printDestruction) print("destroyed 2")
}
Rectangle {
width: view.width; height: view.height
color: "#F4F0FF"
Text { text: "Page 3"; font.bold: true; anchors.centerIn: parent }

Component.onDestruction: if (printDestruction) print("destroyed 3")
}
}

ListView {
id: view
anchors { fill: parent; bottomMargin: 30 }
model: itemModel
preferredHighlightBegin: 0; preferredHighlightEnd: 0
highlightRangeMode: ListView.StrictlyEnforceRange
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem; flickDeceleration: 2000
cacheBuffer: 200
}
//! [0]
Rectangle {
width: root.width; height: 30
anchors { top: view.bottom; bottom: parent.bottom }
color: "gray"

Row {
anchors.centerIn: parent
spacing: 20

Repeater {
model: itemModel.count

Rectangle {
width: 5; height: 5
radius: 3
color: view.currentIndex == index ? "blue" : "white"

MouseArea {
width: 20; height: 20
anchors.centerIn: parent
onClicked: view.currentIndex = index
}
}
}
}
}
}



//AndroidDelegate.qml /*dynamic widget*/

import QtQuick 2.0
import "qrc:/componentCreation.js" as MyScript

Rectangle {
id: appWindow
width: 300; height: 300
color: "#000000"
Component.onCompleted: MyScript.createSpriteObjects();
}

//componentCreation.js

var component;
var sprite;
function createSpriteObjects() {
component = Qt.createComponent("qrc:/qml/res/layouts/ListPage.qml");
if (component.status == Component.Ready)
finishCreation();
else
component.statusChanged.connect(finishCreation);
}
function finishCreation() {
if (component.status == Component.Ready) {
sprite = component.createObject(appWindow, {"x": 100, "y": 100});
if (sprite == null) {
// Error Handling
console.log("Error creating object");
}
} else if (component.status == Component.Error) {
// Error Handling
console.log("Error loading component:", component.errorString());
}
}


I have not included the animation code as I am trying to understand it and use it, above code compiles and runs.
any help and direction will be really helpful.
thanks :)

anda_skoa
7th March 2016, 22:40
From the description of the behavior this sounds like it would be a lot easier to do both screens in QML in the same view.

Cheers,
_

smrati.johri
8th March 2016, 01:52
hello,

Can you please elaborate with an example.
actually, going forward we might have multiple qmls and dynamic object(qml).
and the screen size will be fixed in which we want sliding effect for all the screens

below is code code snippet I was trying today. though it is not working.



//mainwindow.cpp
void MainWindow ::addNewImage()
{

QQuickWidget *mQQuickWidget1 = new QQuickWidget();

//QWidget *container1 = QWidget::createWindowContainer(view1,this );
mQQuickWidget1->setSource(QUrl("qrc:/qml/res/layouts/AndroidDelegate.qml"));
ui->verticalLayout->insertWidget(ui->verticalLayout->count() - 1,mQQuickWidget1,0,Qt::AlignCenter);
/*newly added code for animation*/
QPropertyAnimation *animation = new QPropertyAnimation(mQQuickWidget1,"pos",this);
QRect pix = QRect(QPoint(0,0), mQQuickWidget1->size());
pix.moveCenter(QPoint(width()/2,0));

animation->setDuration(2000);
animation->setStartValue(QPoint(-(mQQuickWidget1->width()),mQQuickWidget1->x()));
animation->setEndValue(QPoint(pix.y(),mQQuickWidget1->x()));
// animation->easingCurve(QEasingCurve::OutBounce);
animation->start();

mQQuickWidget->hide();
}

anda_skoa
8th March 2016, 09:45
Can you please elaborate with an example.

You could put both items into a Flickable and animate its contextX property.
Or put both items into a VisualItemModel and use a ListView.



below is code code snippet I was trying today. though it is not working.

That's again trying to move a widget, I doubt that is what you need.

Cheers,
_

smrati.johri
8th March 2016, 17:03
hi,

thanks for elaborating :)


put both items into a VisualItemModel and use a ListView
while I was trying to implement I found that VisualItemModel is not suggested to be used for dynamic objects/widgets. please correct me if I am wrong.
Also, I can not put them all in a list as going forward we might be having multiple dynamic screens(some widgets as well), which will be generated at various stages.

And I was able to animate it. my one widget is sliding out of screen and another entering in. Below is the working code for the same.

QQuickWidget *mQQuickWidget1 = new QQuickWidget();
mQQuickWidget1->setSource(QUrl("qrc:/qml/res/layouts/AndroidDelegate.qml"));
ui->verticalLayout->addWidget(mQQuickWidget1);
//ui->verticalLayout->insertWidget(ui->verticalLayout->count() - 1,mQQuickWidget1);
/*animate first widget*/
QPropertyAnimation *animation1 = new QPropertyAnimation(mQQuickWidget,"geometry");
QRect pixEnd1 = QRect(QPoint(mQQuickWidget->width(),0), mQQuickWidget->size());
QRect pixStart1 = QRect(QPoint(0,0), mQQuickWidget->size());
animation1->setDuration(5000);
animation1->setStartValue(pixStart1);
animation1->setEndValue(pixEnd1);

animation1->start();
QPropertyAnimation *animation = new QPropertyAnimation(mQQuickWidget1,"geometry");
QRect pixEnd = QRect(QPoint(0,0), mQQuickWidget1->size());
QRect pixStart = QRect(QPoint(-(mQQuickWidget->width()),0), mQQuickWidget1->size());
animation->setDuration(5000);
animation->setStartValue(pixStart);
animation->setEndValue(pixEnd);
animation->start();

But still there is a problem:
as soon as the widget is created and before the animation starts it shows up for faction of seconds and then enters with animation.
I want to get rid of this initial showup of the widget, please help :)