基于QML2.0的View之PathView

继QML2.0TabView之后,打算简单说下PathView这个QML视图,最近找到先前研究的项目,但是对于PathView这个在qml2.0里面继续出现的旧东西,感觉好熟悉,看看qml2.0是否新增了一些特性或者修复了哪些bug,遂研究了下。

Properties
 
cacheItemCount : int
count : int
currentIndex : int
currentItem : Item
delegate : Component
dragMargin : real
dragging : bool
flickDeceleration : real
flicking : bool
highlight : Component
highlightItem : Item
highlightMoveDuration : int
highlightRangeMode : enumeration
interactive : bool
maximumFlickVelocity : real
model : model
moving : bool
offset : real
path : Path
pathItemCount : int
preferredHighlightBegin : real
preferredHighlightEnd : real
snapMode : enumeration
Attached Properties
 
isCurrentItem : bool
onPath : bool
view : PathView
Signals
 
dragEnded()
dragStarted()
flickEnded()
flickStarted()
movementEnded()
movementStarted()
Methods
 
decrementCurrentIndex()
incrementCurrentIndex()
int indexAt(int x, int y)
Item itemAt(int x, int y)
positionViewAtIndex(int index, PositionMode mode)

以上是PathView的一些属性,还有信号,还有方法,各位可以参阅英译汉,懒得不想翻译

个人比较喜欢C++与QML混合编程,应该纯QML可能对于数据处理部分很是吃力,所以部分数据处理放置C++,这样是比较好,UI都是QML来实现

看下C++部分代码:

widget.h部分

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QtDeclarative/QtDeclarative>
#include <QGraphicsObject>
#include <QParallelAnimationGroup>
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    Widget(QWidget *parent = 0);
    ~Widget();
 
    QDeclarativeView* lolView;
    QGraphicsObject* lolObj;
    QParallelAnimationGroup* qrGroup;
    QString lolJson;
    void showQMLView();
    QString pingzhuangJson(QList<QStringList>);
    void showAnimation();
    QList<QStringList> getFileName(QString str);
public slots:
    void slotClose(QVariant,int);
    void slotQrFinishedAnimation();
};
 
#endif // WIDGET_H

widget.cpp部分

#include "widget.h"
#include <QApplication>
#include <QDesktopWidget>
Widget::Widget(QWidget *parent)
    : QWidget(parent),lolView(NULL)
{
    QList<QStringList> lst=getFileName("./qml/CoverFlowQuickApp/lol/");
    lolJson = pingzhuangJson(lst);
}
 
Widget::~Widget()
{
 
}
void Widget::showQMLView()
{
    if(NULL==lolView){
        qDebug() << "hello in  Show Log view1";
        lolView = new QDeclarativeView(0);
        lolView->setMinimumSize(QSize(1320,800));
        lolView->setSource(QUrl("qrc:qml/CoverFlowQuickApp/main.qml"));
        lolView->setWindowFlags(Qt::FramelessWindowHint);
        lolView->setAttribute(Qt::WA_TranslucentBackground);
        lolView->setStyleSheet("background:transparent;");
        lolView->setWindowTitle(QString::fromUtf8("LOL客户端"));
        lolObj = lolView->rootObject();
        connect(lolObj,SIGNAL(signalsendClose(QVariant,int)),this,SLOT(slotClose(QVariant,int)));
    }
    QMetaObject::invokeMethod(lolView->rootObject(),"getJsonfromWidget",
                              Q_ARG(QVariant,QVariant::fromValue(lolJson)));
    lolView->move(((QApplication::desktop()->width()/2)-(lolView->width()/2)),((QApplication::desktop()->height()/2)-(lolView->height()/2)));
    lolView->show();
}
 
QString Widget::pingzhuangJson(QList<QStringList> lst)
{
    QString strJson ="{\"response\":100,\"message\":\"xxxxxx\",\"data\":{\"lolinfo\":{\"lol_info\":[";
    for(int i=0;i<lst.count();i++){
        strJson += "{";
        strJson.append("\"userid\":");
        strJson.append("\""+QString::number(i)+"\"");
        strJson.append(",\"icon\":");
        strJson.append("\"lol/"+lst.at(i).at(0)+"\"");
        strJson.append(",\"name\":");
        QString tmp = lst.at(i).at(1);
        tmp.chop(4);
        strJson.append("\""+tmp+"\"");
        strJson.append("},");
    }
    strJson.chop(1);
    strJson.append("]}}}");
    //qDebug()<<"strJsonstrJsonstrJson "<<strJson;
    return strJson;
}
QList<QStringList> Widget::getFileName(QString str){
//"./qml/CoverFlowQuickApp/lol/
    QString root = str;
    QDir rootDir(root);
    QStringList strings;
    strings << "*.png" ;
    QStringList fileList;
    QString fileListName;
    QList<QStringList> listVetor;
    QFile file("./lol.txt");
    QFileInfoList list = rootDir.entryInfoList(strings);
    for(int i=0;i<list.count();i++)
    {
        QFileInfo tmpInfo= list.at(i);
        if(tmpInfo.isFile() && !(tmpInfo.baseName().contains("close")))
        {
            QString fileName = tmpInfo.fileName();
            fileListName.append(tmpInfo.baseName());
            fileListName.append("\n");
            fileList.append(fileName);
            if(fileList.count() == 5){
                listVetor.append(fileList);
                fileList.clear();
            }
        }
    }
    qDebug()<<"listVetor "<<listVetor<<listVetor.count();
    return listVetor;
}
void Widget::showAnimation()
{
    qrGroup = new QParallelAnimationGroup;
    connect(qrGroup,SIGNAL(finished()),this,SLOT(slotQrFinishedAnimation()));
    QPropertyAnimation *animation2 = new QPropertyAnimation(lolView, "size");
    animation2->setDuration(1000);
    animation2->setStartValue(QSize(this->width(),this->height()));
    animation2->setEndValue(QSize(0,0));
 
    QPropertyAnimation *animation4 = new QPropertyAnimation(lolView, "windowOpacity");
    animation4->setDuration(800);
    animation4->setStartValue(1.0);
    animation4->setEndValue(0.0);
 
    animation2->setEasingCurve(QEasingCurve::OutCubic);
    animation4->setEasingCurve(QEasingCurve::OutCubic);
    qrGroup->addAnimation(animation2);
    qrGroup->addAnimation(animation4);
    qrGroup->start();
}
void Widget::slotQrFinishedAnimation()
{
    qApp->quit();
}
void Widget::slotClose(QVariant var,int iType)
{
    int localx;
    int localy;
    qDebug()<<""<<iType<<" "<<var;
    if(iType == 0){
        QStringList lst=var.toStringList();
        if(lst.count()==2){
            localx = lolView->x();
            localy = lolView->y();
            lolView->move(localx + lst.at(0).toInt(), localy+lst.at(1).toInt());
        }
    }else{
        showAnimation();
//        qApp->quit();
    }
}

这个类 主要是加载本地图片发生到QML来实现图片预览,另外增加了动画关闭窗口功能,关闭应用等

再来看下QML部分

import QtQuick 1.1
 
Item {
    width: 120*11; height: 800
    signal signalsendClose(variant strclose,int iType)
 
    ListModel {
        id: appModel
//        ListElement { name: "弗力贝尔"; icon: "lol/Volibear_Square_0.png" }
//        ListElement { name: "沃里克"; icon: "lol/Warwick_Square_0.png" }
//        ListElement { name: "齐勒斯"; icon: "lol/Xerath_Square_0.png" }
//        ListElement { name: "XinZhao_Square_0"; icon: "lol/XinZhao_Square_0.png" }
//        ListElement { name: "Yorick_Square_0"; icon: "lol/Yorick_Square_0.png" }
//        ListElement { name: "Ziggs_Square_0"; icon: "lol/Ziggs_Square_0.png" }
//        ListElement { name: "Zilean_Square_0"; icon: "lol/Zilean_Square_0.png" }
//        ListElement { name: "Zyra_Square_0"; icon: "lol/Zyra_Square_0.png" }
//        ListElement { name: "Nidalee_Square_0"; icon: "lol/Nidalee_Square_0.png" }
//        ListElement { name: "Nocturne_Square_0"; icon: "lol/Nocturne_Square_0.png" }
//        ListElement { name: "Nunu_Square_0"; icon: "lol/Nunu_Square_0.png" }
//        ListElement { name: "Olaf_Square_0"; icon: "lol/Olaf_Square_0.png" }
//        ListElement { name: "Fiddlesticks_Square_0"; icon: "lol/Fiddlesticks_Square_0.png" }
//        ListElement { name: "Fiora_Square_0"; icon: "lol/Fiora_Square_0.png" }
//        ListElement { name: "Fizz_square_0"; icon: "lol/Fizz_square_0.png" }
//        ListElement { name: "Galio_Square_0"; icon: "lol/Galio_Square_0.png" }
    }
    //    property XmlListModel tmpModel;
    //    XmlListModel {
    //        id: xmlModel
    //        source:"qrc:/qml/CoverFlowQuickApp/pics/lol.xml"
    //        query: "/lol/lolel/File"
    //        XmlRole { name: "fileName"; query: "fileName/string()" }
    //        XmlRole { name: "filePng"; query: "filePng/string()" }
    //        Component.onCompleted: {
    //            console.log("kasjkashjkashkahksj "+query.toString())
    //            tmpModel = xmlModel;
    //        }
    //    }
    Item{
         id: myText
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        width: parent.width
        height: 30
        Text {
             id: myText1
            text: "当前为 -1"
            anchors.centerIn: parent
            font.bold: true
            font.pixelSize: 20
            font.family: "微软雅黑"
        }
    }
    CoverFlow {
        listModel: appModel
        width: parent.width
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: myText.top
        onIndexChanged: {
            myText1.text = "当前为: " + index
        }
        itemWidth: 120
        itemHeight: 120
        color: "black"
    }
    Image {
        source: "lol/close.png"
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.margins: 10
        MouseArea {
            anchors.fill: parent
            onClicked: signalsendClose([""],1);
        }
    }
    MouseArea
    {
        id: backmove
        height: 200
        anchors{
            left: parent.left
            right: parent.right
            rightMargin: 100
            top:parent.top
        }
 
        acceptedButtons: Qt.LeftButton
        property int ix:0
        property int iy:0
        onPressed:
        {
            backmove.ix = mouseX;
            backmove.iy = mouseY;
        }
        onPositionChanged:
        {
            var dyx = mouseX - backmove.ix;
            var dyy = mouseY - backmove.iy;
            var paralist = [dyx,dyy]
            //paralist si windows move offset
            signalsendClose(paralist,0)
        }
    }
 
    function getJsonfromWidget(str){
        console.log("str "+str);
        var jsonObject = eval('(' + str + ')');
        var resultDataObj =  jsonObject.data.lolinfo.lol_info;
        var response = jsonObject.response;
        console.log("refresh data : "+response+" "+resultDataObj[0].icon)
        for(var i =0;i<16;i++)
        {
            if(typeof resultDataObj[i] == "object")
            console.log("refresh: "+resultDataObj[i].name)
            appModel.append(resultDataObj[i]);
        }
    }
}
import QtQuick 1.0
 
Rectangle {
    id: coverFlow
 
    property int itemWidth: 120*listModel.count
    property int itemHeight: 120*listModel.count
 
    property ListModel listModel
 
    property int angleValue: 60
    signal indexChanged(string index)
    gradient: Gradient {
        GradientStop { position: 0.0; color: "black" }
        GradientStop { position: 0.5; color: "gray" }
        GradientStop { position: 1.0; color: "black" }
    }   
    Component {
        id: appDelegate
 
        Flipable {
            id: myFlipable
 
            property bool flipped: false
            property real rotationAngle: PathView.angle
            width: itemWidth; height: itemHeight
            z: PathView.z
            scale: PathView.iconScale
 
            function itemClicked()
            {
                if(PathView.isCurrentItem) {
                    //myFlipable.flipped = !myFlipable.flipped
                    myPathView.interactive = !myFlipable.flipped
                }
                else if(myPathView.interactive) {
                    myPathView.currentIndex = index;
                    console.log("sljaslfajlfjal")
                }
            }
 
            Keys.onReturnPressed: itemClicked()
 
            MouseArea {
                anchors.fill: parent
                onClicked: itemClicked()
            }
            transform: Rotation {
                id: rotation
                origin.x: myFlipable.width/2
                origin.y: myFlipable.height/2
                axis.x: 0; axis.y: 1; axis.z: 0
                angle: rotationAngle
            }
 
            states: State {
                name: "back"
                PropertyChanges { target: rotation; angle: 180 }
                PropertyChanges {target: myFlipable; width: myPathView.width; height: myPathView.height }
                when: myFlipable.flipped
            }
 
            transitions: Transition {
                ParallelAnimation {
                    NumberAnimation { target: rotation; property: "angle"; duration: 250 }
                    NumberAnimation {target: myFlipable; properties: "height,width"; duration: 250}
                }
            }
 
            front: CoverItem{
                id:items
                width: itemWidth
                height: itemHeight*2
                onSignalClickeItem: {
                    console.log("skajfkajffafaf "+iIndex+ " icon "+iconString);
                    backs.curImg = iconString;
                    animationx.stop();
                    animationx.start();
                }
            }
            //            back:
        }
    }
 
    CoverBackItem{
        id:backs
//        width: itemWidth*2
//        height: itemHeight*2
        opacity: 0.0
        z:100
        anchors.centerIn: parent
    }
    SequentialAnimation {
        id:animationx
        NumberAnimation { target: backs; property: "opacity"; to: 1; duration: 500;easing.type: Easing.InQuad }
        PauseAnimation { duration: 500 }
        NumberAnimation { target: backs; property: "opacity"; to: 0; duration: 500;easing.type: Easing.InQuad }
    }
    PathView {
        id: myPathView
 
        Keys.onRightPressed: if (!moving && interactive) incrementCurrentIndex()
        Keys.onLeftPressed: if (!moving && interactive) decrementCurrentIndex()
 
        anchors.fill: parent
        preferredHighlightBegin: 0.5
        preferredHighlightEnd: 0.5
        focus: true
        interactive: true
        model: listModel
        delegate: appDelegate
        path: Path {
            startX: 0
            startY: coverFlow.height / 2
            PathAttribute { name: "z"; value: 100 }
            PathAttribute { name: "angle"; value: angleValue }
            PathAttribute { name: "iconScale"; value: 1.0 }
            PathLine { x: coverFlow.width / 2; y: coverFlow.height / 2;  }
            PathAttribute { name: "z"; value: 0 }
            PathAttribute { name: "angle"; value: 0 }
            PathAttribute { name: "iconScale"; value: 0.7 }
            PathLine { x: coverFlow.width; y: coverFlow.height / 2; }
            PathAttribute { name: "z"; value: 100 }
            PathAttribute { name: "angle"; value: -angleValue }
            PathAttribute { name: "iconScale"; value: 1.0 }
        }
    }
    Item{
         id: myText3
        anchors.top: parent.top
        anchors.topMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
        width: parent.width
        height: 30
        Text {
             id: myText4
            text: "英雄联盟-英雄抉择"
            anchors.centerIn: parent
            font.bold: true
            font.pixelSize: 18
            font.family: "微软雅黑"
            color: "red"
        }
    }
    Component.onCompleted: {
        myPathView.currentIndexChanged.connect(function(){
            //indexChanged(myPathView.currentIndex);
            indexChanged(listModel.get(myPathView.currentIndex).name);
        })
    }
}

话说这里都是qtquick1.1 因为C++里面使用的是QDeclareView来加载qml1,好多看观经常看到报错就是qml1与qml2的view不同导致 或者说纯qml应用和C++、QML混合应用的区别所在。

效果图:

基于QML2.0的View之PathView


稍后附上源码

SourceCode

原文出处:寒山-居士

原文链接:https://blog.csdn.net/Esonpo/article/details/38014211

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论