【Lesson4】跟我写一个“一言”


  • 船长

    源码地址:https://github.com/0312birdzhang/harbour-hitokoto

    API地址: http://hitokoto.cn/api

    一言

    通过摇晃手机或吹一吹话筒来改变一言,也就是随机切换一言

    为了方便,我们这里只讲晃一晃

    Let's begin

    1.新建项目

    要上架旗鱼商店,必须是harbor-xxx 名称的。所以在创建项目的时候就写好,一劳永逸。如这里我叫harbour-hitokoto

    2.添加传感器

    打开rpm/harbour-hitokoto.spec文件,在BuildRequires上面添加下面

    Requires:   qt5-qtdeclarative-import-sensors
    Requires:   qt5-qtsensors-plugin-gestures-shake
    Requires:   qt5-qtsensors-plugin-gestures-sensor
    

    添加完之后的部分配置是这样的

    Source0:    %{name}-%{version}.tar.bz2
    Source100:  harbour-hitokoto.yaml
    Requires:   sailfishsilica-qt5 >= 0.10.9
    Requires:   qt5-qtdeclarative-import-sensors
    Requires:   qt5-qtsensors-plugin-gestures-shake
    Requires:   qt5-qtsensors-plugin-gestures-sensor
    BuildRequires:  pkgconfig(sailfishapp) >= 1.0.2
    BuildRequires:  pkgconfig(Qt5Core)
    BuildRequires:  pkgconfig(Qt5Qml)
    BuildRequires:  pkgconfig(Qt5Quick)
    BuildRequires:  desktop-file-utils
    
    %description
    

    3.调用摇动传感器

    在qml/harbor-hitokoto.qml中导入import QtSensors 5.0,然后就可以用SensorGesture

    SensorGesture {
            id:gestureid
            gestures : ["QtSensors.shake"]
            enabled: true
            onDetected:{
                //检测到晃动,干一些事
            }
        }
    

    我们新建一个main.js,来进行网络请求等。
    main.js内容如下:

    .pragma library
    
    var api = "https://sslapi.hitokoto.cn/?encode=json";
    var signalcenter;
    function sendWebRequest(url, callback, method, postdata) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function() {
                    switch(xmlhttp.readyState) {
                    case xmlhttp.OPENED:signalcenter.loadStarted();break;
                    case xmlhttp.HEADERS_RECEIVED:if (xmlhttp.status != 200)signalcenter.loadFailed(qsTr("error connection:")+xmlhttp.status+"  "+xmlhttp.statusText);break;
                    case xmlhttp.DONE:if (xmlhttp.status == 200) {
                            try {
                                callback(xmlhttp.responseText);
                                signalcenter.loadFinished();
                            } catch(e) {
                                console.log(e)
                                signalcenter.loadFailed(qsTr("loading erro..."));
                            }
                        } else {
                            signalcenter.loadFailed("");
                        }
                        break;
                    }
                }
        if(method==="GET") {
            xmlhttp.open("GET",url);
            xmlhttp.send();
        }
        if(method==="POST") {
            xmlhttp.open("POST",url);
            xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xmlhttp.setRequestHeader("Content-Length", postdata.length);
            xmlhttp.send(postdata);
        }
    }
    
    function gethitokoto(){
        sendWebRequest(api, loadResult, "GET","");
    }
    
    var app;
    function loadResult(oritxt){
        var obj = JSON.parse(oritxt);
        //console.log(oritxt)
        app.hitokoto = obj.hitokoto;
        app.author = obj.creator;
        app.source = obj.from;
        app.catname = obj.type;
    }
    
    
    

    创建一个SignalCenter.qml,内容如下:

    import QtQuick 2.0
    import Sailfish.Silica 1.0
    
    QtObject{
             id:signalcenter;
             signal loadStarted;
             signal loadFinished;
             signal loadFailed(string errorstring);
    }
    

    4.要开始装逼了(笑

    在qml/harbor-hitokoto.qml中导入main.js

    import main.js as Main

    然后...

    emmmmmmmm....

    我还是直接贴代码吧

    import QtQuick 2.0
    import Sailfish.Silica 1.0
    import QtSensors 5.0
    import "./main.js" as JS
    
    ApplicationWindow{
        id: window
        property string hitokoto;
        property string  source
        property string  author
        property string  catname
        property bool loading: false
        cover: Qt.resolvedUrl("cover/CoverPage.qml")
        allowedOrientations: Orientation.Portrait
        _defaultPageOrientations: Orientation.Portrait
    
        BusyIndicator {
            id: busyIndicator
            anchors.centerIn: parent
            running: loading
            size: BusyIndicatorSize.Large
        }
    
    
    
        Connections{
            target: signalcenter;
            onLoadStarted:{
                window.loading=true;
            }
            onLoadFinished:{
                window.loading=false;
            }
            onLoadFailed:{
                window.loading=false;
                detectedText.text = errorstring;
            }
        }
    
        Signalcenter{
            id:signalcenter
        }
    
        SensorGesture {
            id:gestureid
            gestures : ["QtSensors.shake"]
            enabled: true
            onDetected:{
                JS.gethitokoto()
            }
        }
    
    
    
        SilicaFlickable{
            anchors.fill: parent
            contentHeight: detectedText.height + contentExt.height + Theme.paddingMedium
            Label{
                id:detectedText
                anchors{
                    left:parent.left
                    right:parent.right
                    margins: Theme.paddingMedium
                }
                y:window.height / 2 - detectedText.height /2
                width: parent.width
                wrapMode: Text.WordWrap
                font.pixelSize: Theme.fontSizeLarge
                color: Theme.highlightColor
                opacity:0.7
                font.bold: true
                horizontalAlignment: Text.AlignLeft
                truncationMode: TruncationMode.Elide
                text: getRandomIcon()+ ": "+hitokoto
                MouseArea{
                    anchors.fill: parent
                    onPressAndHold: {
                        Clipboard.text = hitokoto;
                    }
                }
            }
            Label{
                id:contentExt
                text:"——"+(source?(source+","):"")
                width:parent.width * 0.7
                wrapMode: Text.WordWrap
                font.pixelSize:Theme.fontSizeSmall
                horizontalAlignment: Text.AlignRight
                anchors{
                    top:detectedText.bottom
                    right:parent.right
                    margins: Theme.paddingMedium
                }
            }
    
        }
        Component.onCompleted: {
            JS.signalcenter = signalcenter
            JS.app = window
            JS.gethitokoto();
        }
    }
    

登录后回复