Canonical Voices

What Ubuntu Touch Development in CSDN (Chinese) talks about

UbuntuTouch

粒子是计算机图形技术,可视化某些图形效果。典型的影响可能是:落叶,火灾,爆炸,流星,云,等。

它不同于其他的图形渲染原因粒子渲染是基于模糊的方面。结果是不能在像素基底准确预测的。参数到粒子系统描述为随机模拟的边界。与粒子渲染的现象,往往很难与传统的渲染技术,可视化。好处是可以让要素QML与粒子系统交互。可以使用传统的动画技术动画通过属性的控制来实现动画效果。


概念


在粒子模拟的心脏是控制共享时间线的ParticleSystem。一个场景可以有几个粒子系统,他们每个人具有独立的时间线。一个粒子是使用Emitter发射并用ParticlePainter来呈现,它可以是图像,QML项。发射器也提供了用于控制粒子向量空间的方向。一旦粒子被发射,它将不再被发射器所控制。粒子模块提供Affector,它用来操控粒子被发射后的行为。
在一个系统中的颗粒可以共享使用ParticleGroup元件定时切换。默认情况下,每一个粒子都是属于是空的('')组。


  • ParticleSystem - manages shared time-line between emitters
  • Emitter - emits logical particles into the system
  • ParticlePainter - particles are visualized by a particle painter
  • Direction - vector space for emitted particles
  • ParticleGroup - every particle is a member of a group
  • Affector - manipulates particles after they have been emitted
一个粒子系统基本是由ParticleSystem、ImageParticle(ParticlePainter)以及Emitter组成的。其中ParticleSystem必不可少,因为这是要控制好各个粒子系统组件的必备类型。如果ParticleSystem是不作为Emitter的父类存在的话,那么Emitter有一个成员system必须要指定ParticleSystem的id。Emitter也是一个必不可少的类,它的作用是规定这些例子以何种方式发射、以及规定粒子的大小和生命周期。而ImageParticle是ParticlePainter的子类,它不是必备的,我们可以采用ParticlePainter的其它子类CustomParticle和ItemParticle来指定。它的作用是规定粒子的图片以及旋转、颜色、透明度等信息。

其实在三者之外,还有一个不可忽视的类,那就是Affector。一般来说,粒子在Emitter作用后会保持初始的速度、加速度和大小进行运动,此后这些数值不再受Emitter控制了,只有Affector才能控制粒子在运行过程中的数值大小。这里Affector只是一个基类,在它的基础上定义出来了很多根据不同效果而定义的子类。比如说Age、Attractor、Friction、Gravity、GroupGoal、SpriteGoal、Turbulence和Wander。

我们先来做一个简单的例子:

Main.qml


import QtQuick 2.0
import QtQuick.Particles 2.0
import Ubuntu.Components 1.1


MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "particle1.liu-xiao-guo"

    width: units.gu(100)
    height: units.gu(75)

    Page {
        title: i18n.tr("particle1")

        ParticleSystem {
            id: particle
            anchors.fill: parent
            running: true

            ImageParticle {
                anchors.fill: parent
//                source: "qrc:///particleresources/star.png"
                source: "images/starfish_1.png"
                alpha: 0.5
                alphaVariation: 0.2
                colorVariation: 1.0
            }

            Emitter {
                anchors.centerIn: parent
                emitRate: 400
                lifeSpan: 5000
                size: 20
                sizeVariation: 8
                velocity: AngleDirection {angleVariation: 180; magnitude: 60}
            }

            Turbulence {
                anchors.fill: parent
                strength: 2
            }
        }
    }
}

在上面的例子中,我们使用了一个ImageParticle.它继承于ParticlePainter.用来显示每个粒子.我们同时也定义了一个发射器.在里面我们可以定义每个粒子的生命期,大小,方向及大小.运行我们的应用:



我们可以修改上面的例程的一些参数,比如我们修改AngleDirection里的角度就图片.



上面的例程的源码在https://gitcafe.com/ubuntu/particle1 我们上面的代码也可以使用如下的格式:

    Page {
        title: i18n.tr("particle3")

        ParticleSystem {
            id: particleSystem
        }

        Emitter {
            id: emitter
            anchors.centerIn: parent
            anchors.fill: parent
            system: particleSystem
            emitRate: 10
            lifeSpan: 2000
            lifeSpanVariation: 500
            size: 54
            endSize: 32
        }

        ImageParticle {
            source: "images/realLeaf1.png"
            system: particleSystem
        }
    }

这里Emitter不再被ParticleSystem所包含,但是我们必须在里面定义一个叫做system的属性.

我们修改我们上面的例子.我们使用Gravity Affector. 在Gravity中,我们可以使用加速度及角度.整个例程的代码为:


import QtQuick 2.0
import Ubuntu.Components 1.1
import QtQuick.Particles 2.0

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "particle2.liu-xiao-guo"

    width: units.gu(100)
    height: units.gu(75)

    Page {
        title: i18n.tr("particle2")

        ParticleSystem
        {
            anchors.centerIn: parent
            running: true

            ImageParticle {
                anchors.fill: parent
                // source: "qrc:///particleresources/star.png"
                source: "images/starfish_0.png"
                alpha: 0.5
                alphaVariation: 0.2
                colorVariation: 1.0
            }

            Emitter
            {
                emitRate: 20
                size: 50
                lifeSpan: 5000
                velocity: AngleDirection { magnitude: 100; angleVariation: 360  }
            }

            Gravity
            {
                angle: 90
                magnitude: 100
            }

            Turbulence {
                anchors.fill: parent
                strength: 2
            }
        }
    }
}

运行我们的例程,效果如下:


如上图所示,我们可以看到一种重力的效果.整个项目的源码在 https://gitcafe.com/ubuntu/particle2


作者:UbuntuTouch 发表于2016/2/2 11:08:08 原文链接
阅读:136 评论:0 查看评论

Read more
UbuntuTouch

[原]在QML应用中显示image tag

我们在许多的手机中应用中可以看见在文字中可以插入图片.这对于我们的有些应用添加很多的情趣.在今天的例程中,我们通过一个很小的例程来展示如何实现同样的功能.


   


要实现上面的功能其实并不难.我们首先来看一下QML中的Text的用法.

text : string
The text to display. Text supports both plain and rich text strings.

从上面的描述中,我们可以看出Text是支持plain及rich text的.也就是说,它支持像HTML格式的文本输出.基于这样的特性,我们可以设计我们的程序如下:

TextWithImage.qml


import QtQuick 2.0

Text {
    width: parent.width
    font.pointSize: 30
    wrapMode: Text.WordWrap
    textFormat: Text.StyledText
    horizontalAlignment: main.hAlign
}

Main.qml

import QtQuick 2.0
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "imagetag.liu-xiao-guo"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(60)
    height: units.gu(85)

    Page {
        id: main
        title: i18n.tr("Image Tags")

        property var hAlign: Text.AlignLeft

        Flickable {
            anchors.fill: parent
            anchors.bottomMargin:buttons.height
            contentWidth: parent.width
            contentHeight: col.height + 20

            Column {
                id: col
                x: 10; y: 10
                spacing: 20
                width: parent.width - 20

                TextWithImage {
                    text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\">"
                }
                TextWithImage {
                    text: "This is a <b>very<img src=\"images/face-smile-big.png\" align=\"middle\"/>happy</b> face vertically aligned in the middle."
                }
                TextWithImage {
                    text: "This is a tiny<img src=\"images/face-smile.png\" width=\"15\" height=\"15\">happy face."
                }
                TextWithImage {
                    text: "This is a<img src=\"images/starfish_2.png\" width=\"50\" height=\"50\" align=\"top\">aligned to the top and a<img src=\"images/heart200.png\" width=\"50\" height=\"50\">aligned to the bottom."
                }
                TextWithImage {
                    text: "Qt logos<img src=\"images/qtlogo.png\" width=\"55\" height=\"60\" align=\"middle\"><img src=\"images/qtlogo.png\" width=\"37\" height=\"40\" align=\"middle\"><img src=\"images/qtlogo.png\" width=\"18\" height=\"20\" align=\"middle\">aligned in the middle with different sizes."
                }
                TextWithImage {
                    text: "Some hearts<img src=\"images/heart200.png\" width=\"20\" height=\"20\" align=\"bottom\"><img src=\"images/heart200.png\" width=\"30\" height=\"30\" align=\"bottom\"> <img src=\"images/heart200.png\" width=\"40\" height=\"40\"><img src=\"images/heart200.png\" width=\"50\" height=\"50\" align=\"bottom\">with different sizes."
                }
                TextWithImage {
                    text: "Resized image<img width=\"48\" height=\"48\" align=\"middle\" src=\"http://qt-project.org/images/qt13a/Qt-logo.png\">from the internet."
                }
                TextWithImage {
                    text: "Image<img align=\"middle\" src=\"http://qt-project.org/images/qt13a/Qt-logo.png\">from the internet."
                }
                TextWithImage {
                    height: 120
                    verticalAlignment: Text.AlignVCenter
                    text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\"> with an explicit height."
                }
            }
        }

        Keys.onUpPressed: main.hAlign = Text.AlignHCenter
        Keys.onLeftPressed: main.hAlign = Text.AlignLeft
        Keys.onRightPressed: main.hAlign = Text.AlignRight

        Row {
            id: buttons
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            spacing: units.gu(2)

            Button {
                text: "Align Left"
                onClicked: {
                    main.hAlign = Text.AlignLeft
                }
            }

            Button {
                text: "Align Center"
                onClicked: {
                    main.hAlign = Text.AlignHCenter
                }
            }

            Button {
                text: "Align Right"
                onClicked: {
                    main.hAlign = Text.AlignRight
                }
            }
        }
    }
}

在上面,我们可以看出来,我们在Text中使用了HTML格式的文本输出.这样就可以生成就像我们在文章开始部分显示的应用输出.

应用所有的源码在:https://gitcafe.com/ubuntu/imagetag





作者:UbuntuTouch 发表于2016/1/14 15:18:16 原文链接
阅读:245 评论:0 查看评论

Read more
UbuntuTouch

在这篇文章中,我们将展示如何在我们的QML应用中使用不同的font.我们既可以使用本地应用带有的字体,也可以使用系统带有的字体.我们也展示了如何使用一个在网路上的字体.


为了使用字体,我们可以通过如下的方式来使用它:


       Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: "Times"
            font.pixelSize: size
        }

具体的使用说明可以参考连接QML Text.当然,我们也可以使用一种简洁的格式:

       Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            horizontalAlignment: Text.AlignHCenter
            font { family: "Times"; pixelSize: size; capitalization: Font.AllUppercase }
        }


我们可以在上面一行中定义font的所有的属性.

为了使用不同的font,我们可以使用FontLoader来装载我们的font:

    FontLoader { id: fixedFont; name: "Courier" }
    FontLoader { id: localFont; source: "content/fonts/tarzeau_ocr_a.ttf" }
    FontLoader { id: webFont; source: "http://www.princexml.com/fonts/steffmann/Starburst.ttf" }

在上面的代码中,我们使用了本地的Courier字体,我们也使用了在本地文件目录中的字体tarzeau_ocr_a.ttf,同时我们也定义了一个网路的字体.该字体文件存在于网路的一个地址.在实际的使用中,该字体将本载入到我们的应用中使用.

为了说明问题,我们直接把我的源码写出来:

Fonts.qml

import QtQuick 2.0

Rectangle {
    property string myText: "The quick brown fox jumps over the lazy dog."

    width: 320; height: 480
    color: "steelblue"

    FontLoader { id: fixedFont; name: "Courier" }
    FontLoader { id: localFont; source: "content/fonts/tarzeau_ocr_a.ttf" }
    FontLoader { id: webFont; source: "http://www.princexml.com/fonts/steffmann/Starburst.ttf" }
    property int size: 40

    Column {
        anchors { fill: parent; leftMargin: 10; rightMargin: 10; topMargin: 10 }
        spacing: 15

        Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: "Times"
            font.pixelSize: size
        }
        Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            horizontalAlignment: Text.AlignHCenter
            font { family: "Times"; pixelSize: size; capitalization: Font.AllUppercase }
        }
        Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            horizontalAlignment: Text.AlignRight
            wrapMode: Text.WordWrap
            font { family: fixedFont.name; pixelSize: size; weight: Font.Bold; capitalization: Font.AllLowercase }
        }
        Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            font { family: fixedFont.name; pixelSize: size; italic: true; capitalization: Font.SmallCaps }
        }
        Text {
            text: myText
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            font { family: localFont.name; pixelSize: size; capitalization: Font.Capitalize }
        }
        Text {
            text: {
                if (webFont.status == FontLoader.Ready) myText
                else if (webFont.status == FontLoader.Loading) "Loading..."
                else if (webFont.status == FontLoader.Error) "Error loading font"
            }
            color: "lightsteelblue"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: webFont.name; font.pixelSize: size
        }
    }
}

运行我们的应用,显示的画面为:



我们的源码地址为:https://github.com/liu-xiao-guo/fonts




作者:UbuntuTouch 发表于2016/1/4 8:27:17 原文链接
阅读:320 评论:0 查看评论

Read more
UbuntuTouch

在这篇文章中,我们来显示在Ubuntu 手机中所有的已经有的字体.大家可以根据自己的需求来选择自己所需要的字体.我们已经在先前的文章" 如何在QML中使用不同的字体(font)"已经展示了如何使用font来显示不同的字体.


我们可以通过如下的方式来显示所有的字体:


AvailableFonts.qml


import QtQuick 2.0
import Ubuntu.Components 1.1

Rectangle {
    color: "steelblue"
    property int size: 60

    ListView {
        clip: true
        anchors.fill: parent
        model: Qt.fontFamilies()

        delegate: Item {
            height: units.gu(4)
            width: ListView.view.width

            Row {
                height: parent.height
                width: parent.width

                Text {
                    anchors.verticalCenter: parent.verticalCenter
                    text: "I love you!"
                    width: units.gu(25)
                    font { family: modelData; pixelSize: size }
                }

                Text {
                    anchors.verticalCenter: parent.verticalCenter
                    text: modelData
                    color: "white"
                }
            }

            Rectangle {
                color: "red"
                height: 2
                width: parent.width
            }
        }
    }
}


在我们的Main.qml中,我们直接调用:

Main.qml


import QtQuick 2.0
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "fontlist.liu-xiao-guo"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(60)
    height: units.gu(85)

    Page {
        title: i18n.tr("Font list")

        Text {
            id: txt
            anchors.top: parent.top
            anchors.horizontalCenter: parent.horizontalCenter
            text: "我爱你 " + font.family + " " + font.pixelSize
            height: units.gu(3)
        }

        AvailableFonts {
            anchors.fill: parent
            anchors.topMargin:txt.height
        }
    }
}


运行我们的应用:




作者:UbuntuTouch 发表于2016/1/4 9:25:26 原文链接
阅读:259 评论:0 查看评论

Read more
UbuntuTouch

[原]snappy ubuntu core 演示

基于对snappy ubuntu core的理解,我做了几个展示的应用.


1)利用snappy ubuntu core来控制piglow


2)利用snappy ubuntu core来收集传感器数据及控制LED灯



3)利用snappy ubuntu core来监控webcam



更多关于snappy ubuntu core的介绍,可以参阅文章"到底Snappy Ubuntu是什么?".也可以参考我们的全球网站developer.ubuntu.com/snappy来了解更多信息.
作者:UbuntuTouch 发表于2016/1/12 14:09:45 原文链接
阅读:267 评论:0 查看评论

Read more
UbuntuTouch

[原]利用Javascript来创建Ubuntu Scope

在先前的教程"在Ubuntu OS上创建一个dianping Scope (Qt JSON)",我们知道如何使用C++来在Ubuntu平台上开发一个Scope;我们也在文章"使用golang来设计我们的Ubuntu Scope"里展示了如何使用go语言来在Ubuntu上开发一个Scope.在今天的文章中,我们来展示如何利用Javascript语言来开发一个Scope.这对于一些网页开发的开发者来说,无疑是一个天大的好消息,因为你们不需要学习另外一种语言就可以轻松地开发一个属于你们自己的Scope.更多关于Scope开发的知识可以在网址https://developer.ubuntu.com/en/scopes/


1)安装

首先我们必须强调的是Javascrip支持Scope的开发始于Ubuntu 15.04(vivid)系统及以后的版本.在开发之前,开发者必须按照文章"Ubuntu SDK 安装"安装好自己的SDK.同时,必须做如下的JS Scope开发工具的安装:

$ sudo apt install unity-js-scopes-dev
$ unity-js-scopes-tool setup

在这里必须注意的是,我们必须在安装完我们的Ubuntu SDK后才可以执行上面的安装,并在SDK的安装中chroots必须安装完整.经过上面的安装,我们基本上已经完成了我们所有的工具的安装.


2)JS Scope开发文档



所有的开发离不开我们所需要的技术文档.JS Scope的开发文档的地址可以在early build找到.当然你们也可以通过安装unity-js-scopes-doc包来得到帮助.


3)创建一个我们的Scope


Webservice API


我们还是使用我们先前使用百度天气API为例.该API的连接为:


点击上面的连接后,我们可以得到JSON格式的输出:

{"error":0,"status":"success","date":"2016-01-18","results":[{"currentCity":"北京","pm25":"13","index":[{"title":"穿衣","zs":"寒冷","tipt":"穿衣指数","des":"天气寒冷,建议着厚羽绒服、毛皮大衣加厚毛衣等隆冬服装。年老体弱者尤其要注意保暖防冻。"},{"title":"洗车","zs":"较适宜","tipt":"洗车指数","des":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"},{"title":"旅游","zs":"一般","tipt":"旅游指数","des":"天气较好,温度稍低,而且风稍大,让您感觉有些冷,会对外出有一定影响,外出注意防风保暖。"},{"title":"感冒","zs":"极易发","tipt":"感冒指数","des":"天气寒冷,昼夜温差极大且空气湿度较大,易发生感冒,请注意适当增减衣服,加强自我防护避免感冒。"},{"title":"运动","zs":"较不宜","tipt":"运动指数","des":"天气较好,但考虑天气寒冷,风力较强,推荐您进行室内运动,若在户外运动请注意保暖并做好准备活动。"},{"title":"紫外线强度","zs":"弱","tipt":"紫外线强度指数","des":"紫外线强度较弱,建议出门前涂擦SPF在12-15之间、PA+的防晒护肤品。"}],"weather_data":[{"date":"周一 01月18日 (实时:-8℃)","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/qing.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/qing.png","weather":"晴","wind":"北风3-4级","temperature":"-4 ~ -11℃"},{"date":"周二","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/qing.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/duoyun.png","weather":"晴转多云","wind":"微风","temperature":"-1 ~ -8℃"},{"date":"周三","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/duoyun.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/yin.png","weather":"多云转阴","wind":"微风","temperature":"0 ~ -7℃"},{"date":"周四","dayPictureUrl":"http://api.map.baidu.com/images/weather/day/yin.png","nightPictureUrl":"http://api.map.baidu.com/images/weather/night/duoyun.png","weather":"阴转多云","wind":"微风","temperature":"-3 ~ -6℃"}]}]}

我们的Scope需要来解析上面的JSON格式的输出,并在我们的Scope中呈现.


创建一个最基本的scope


在这一节中,我们来创建一个JS Scope.我们可以利用在Ubuntu SDK中所提供的template来轻松地创建一个Scope.首先,我们打开我们的SDK,并且选择"New File or Project":

     


  


  

  

在最后的几步中,我们必须为每个我们所选择的Kit都要做同样的步骤以完成整个项目的生成.我们这时可以运行(点击SDK左下角的绿色按钮)我们的Scope:



显示如下.基本上没有什么特别的东西.它在默认的情况下显示的是一个天气的Scope,我们可以在它里面输入一些我们所感兴趣的城市的名称来得到当前城市的天气情况.我们可以选择SDK屏幕做下角的Desktop或Ubuntu Desktop SDK kit来在Desktop的环境下运行.当我们需要在手机上运行时,我们必须选择Ubuntu SDK for armhf来运行:


  


项目总览及npm集成:


我们在上面已经生产了我们的项目,我们首先来查看一下我们的项目的结构:

liuxg@liuxg:~/release/chinaweatherjs$ tree
.
├── chinaweatherjs.apparmor
├── CMakeLists.txt
├── CMakeLists.txt.user
├── manifest.json.in
├── po
│   ├── chinaweatherjs.pot
│   ├── CMakeLists.txt
│   ├── Makefile.in.in
│   ├── POTFILES.in
│   └── POTFILES.in.in
└── src
    ├── chinaweatherjs.js
    ├── CMakeLists.txt
    ├── data
    │   ├── chinaweatherjs.ini.in
    │   ├── chinaweatherjs-settings.ini.in
    │   ├── icon.png
    │   └── logo.png
    ├── etc
    └── node_modules
        ├── last-build-arch.txt
        └── unity-js-scopes
            ├── bin
            │   └── unity-js-scopes-launcher
            ├── index.js
            ├── lib
            │   └── scope-core.js
            └── unity_js_scopes_bindings.node

8 directories, 20 files

从上面的结构中,我们可以看出来我们的核心的文件将是src/chinaweatherjs.js文件.在node_modules中含有我们所需要的库.如果你先前已经做过一些Scope开发,那么重新利用该文件来构造自己的Scope将是非常简单的.如果你还没有开发过任何其它的Scope的话,那么,请继续阅读我们下面的介绍.

npm集成

细心的开发者可能已经注意到一个叫做node_modules的目录.JS Scope使用的框架就是npm + Scope.我们可以很方便地使用unity-js-scopes-tool来加入我们所需要的npm包到我们的Scope项目中去.运行的命令如下:

$ unity-js-scopes-tool install <path/to/project/src/node_modules> <npm package> 

上述命令将安装任何一个我们所需要的npm包到我们的项目中去.如果你对npm还不是很熟话,请参阅连接https://www.npmjs.com/


API总览

在这一节中,我们将介绍一下我们所使用的API及如何实现我们所需要的Scope.

Javascript Scope的基本架构

为了能够连接到Scope的runtime,你的Scope只需要遵守几个简单的准则:
  • 导入 Javascript Scope模块到你的代码中
  • 设置你的Scope的runtime上下文
这些步骤简单地说就是如下的代码:

var scopes = require('unity-js-scopes')
scopes.self.initialize({}, {});

一旦被导入,unity-js-scopes核心模块即是和Scope runtime交互的入口点.runtime将帮我们设置好我们的Scope,和我们的Dash进行交互及显示用户在Scope交互所生产的结果等.

在上面的初始化代码中,"self"属性是用来帮助我们实现我们的交互.它引用当前正在运行的Scope的上下文.我们可以在上面显示的index.js文件中看到如下的代码:

Object.defineProperty(
    module.exports,
    "self",
    {
        get: function() {
            if (! self) {
                self = new Scope();
            }
            return self;
        },
    });

除了定义一些你的Scope在运行时的一下runtime元素以外,你的runtime上下文还允许你来检查当前Scope的设置及接受scope runtime环境变化时所生产的变化等.


Runtime 元素

现在,我们可以来重新回顾我们的Scope代码并开始定义一些重要的运行时的函数的行为.
一旦我们的Scope和runtime建立起连接并被用户所启动,scope runtime将发送来所有的由用户所产生的动作.最终这些动作将被发送到有我们的Scope在Initialize过程中所定义的API函数中.

这些API函数可以由我们的Scope来有选择地定义.它们将在runtime时反应出那些最重要的被触发的步骤.下面列举那些最重要的runtime回调函数.

  • run: 当一个scope准备运行时,这个回调函数将被调用.
  • start: 当一个scope准备启动时,这个函数将被调用
  • stop: 当一个scope准备停止时,这个函数将被调用
  • search: 当用户请求一个搜索时,这个函数将被调用.runtime将将提供所有的关于搜索所需要的信息给这个函数的调用.开发者的任务就是通过和runtime的交互把所有可能的结果push给runttime.你也可以控制如何显示这些结果
  • preview: 显示一个在上面search中显示结果的preview.runtime将提供关于这个preview所需要的所有的信息
一个简单的模版为:

var scopes = require('unity-js-scopes')
scopes.self.initialize({}, {
    run: function() {
        console.log('Running...');
    },
    start: function(scope_id) {
        console.log('Starting scope id: ' + scope_id + ', ' + scopes.self.scope_config)
    },
    search: function(canned_query, metadata) {
        return null
    },
    preview: function(result, metadata) {
        return null
    },
}});

对于每一个scope runtime的回调函数来说,它相应于一个用户的交互.scope runtime希望你的scope发送回一个描述各个关键交互所需要的对象.
比如,对search回调函数来说,它希望你的scope发送回一个叫做SearchQuery的object.你将使用这个object来定义用户进行搜索时的行为.
SearchQuery object可以定义一个run回调函数.当搜索发生时,该函数将被调用.同时它也可以定义一个cancel的回调函数.当一个搜索被停止时,该函数将被调用.
Scope runtime同时也传入一个叫做SearchReply的object.这个object可以被用来push一些结果到scope runtime.

上面的这种交互模式是贯穿了整个scope及scope rumtime设计的核心交互模式.


推送搜索结果


上面讲到的一个最核心的搜索交互就是我们的scope可以把我们所需要的结果推送到scope runtime.这些结果是通过SearchReply来完成推送的.这个函数希望一个叫做CategorisedResult类型的数据被创建,并被推送到scope runtime.这个result对象将让我们的scope来定义诸如title, icon,uri等信息.

CategorisedResult的一个额外的功能就是在创建它时,可以指定它结果显示的layout.这个layout是由Category及CategoryRender对象共同定义的.下面就是一个我们天气scope中所使用的一个例子.为了能够获取百度天气API的数据,我们必须重新定义tempalate中的变量:

var query_host = "api.map.baidu.com"
var weather_path = "/telematics/v3/weather?output=json&ak=DdzwVcsGMoYpeg5xQlAFrXQt&location="
var URI = "http://www.weather.com.cn/html/weather/101010100.shtml";

initialize中的search方法定义如下:

                search: function(canned_query, metadata) {
                    return new scopes.lib.SearchQuery(
                                canned_query,
                                metadata,
                                // run
                                function(search_reply) {
                                    var qs = canned_query.query_string();
                                    if (!qs) {
                                        qs = "北京"
                                    }

                                    console.log("query string: " + qs);

                                    var weather_cb = function(response) {
                                        var res = '';

                                        // Another chunk of data has been recieved, so append it to res
                                        response.on('data', function(chunk) {
                                            res += chunk;
                                        });

                                        // The whole response has been recieved
                                        response.on('end', function() {
                                            // console.log("res: " + res);

                                            r = JSON.parse(res);

                                            // Let's get the detailed info
                                            var request_date = r.date
                                            console.log("date: " + date);

                                            var city = r.results[0].currentCity;
                                            console.log("city: " + city);

                                            var pm25 = r.results[0].pm25
                                            console.log("pm25: " + pm25)

                                            var category_renderer = new scopes.lib.CategoryRenderer(JSON.stringify(WEATHER_TEMPLATE));
                                            var category = search_reply.register_category("Chineweather", city, "", category_renderer);

                                            try {
                                                r = JSON.parse(res);
                                                var length = r.results[0].weather_data.length
                                                console.log("length: " + length)

                                                for (var i = 0; i < length; i++) {
                                                    var categorised_result = new scopes.lib.CategorisedResult(category);

                                                    var date = r.results[0].weather_data[i].date
                                                    console.log("date: "+  date);

                                                    var dayPictureUrl = r.results[0].weather_data[i].dayPictureUrl;
                                                    console.log("dayPictureUrl: " + dayPictureUrl);

                                                    var nightPictureUrl = r.results[0].weather_data[i].nightPictureUrl;
                                                    console.log("nightPictureUrl: " + nightPictureUrl);

                                                    var weather = r.results[0].weather_data[i].weather;
                                                    console.log("weather: " + weather);

                                                    var wind = r.results[0].weather_data[i].wind;
                                                    console.log("wind: " + wind);

                                                    var temperature = r.results[0].weather_data[i].temperature;
                                                    console.log("temperature: " + temperature);

                                                    categorised_result.set("weather", weather);
                                                    categorised_result.set("wind", wind);
                                                    categorised_result.set("temperature", temperature);

                                                    categorised_result.set_uri(URI);
                                                    categorised_result.set_title("白天: " + date );
                                                    categorised_result.set_art(dayPictureUrl);
                                                    categorised_result.set("subtitle", weather);
                                                    search_reply.push(categorised_result);

                                                    categorised_result.set_title("夜晚: " + date );
                                                    categorised_result.set_art(nightPictureUrl);
                                                    search_reply.push(categorised_result);

                                                }

                                                // We are done, call finished() on our search_reply
//                                              search_reply.finished();
                                            }
                                            catch(e) {
                                                // Forecast not available
                                                console.log("Forecast for '" + qs + "' is unavailable: " + e)
                                            }
                                        });
                                    }

                                    console.log("request string: " + query_host + weather_path + qs);

                                    http.request({host: query_host, path: weather_path + encode_utf8(qs)}, weather_cb).end();
                                },

                                // cancelled
                                function() {
                                });
                },


Preview搜索结果


一旦我们的搜索结果被推送到scope runtime并被显示,用户可以点击显示的结果并请求一个关于该结果的preview.Scope runtime将通过你的scope中所定义的preview回调来显示所需要的结果.

就像我们上面对search所描述的那样,scope runtime希望你的scope返回一个PreViewQuery的对象来作为一个交互的桥梁.这个对象必须指定一个run及一个cancel的函数.这两个函数和我们上面介绍的search中的语义是一样的.这里不再累述.

对Preview来说,有两个最重要的元素:column layout及Preview Widgets.就像它们的名字所描述的那样,column layout元素是用来定义Preview页面中Preview Component的layout的.Preview Widget是用来在Preview页面中组成页面的.

一旦我们明白了上面所讲的,预览插件并且它被绑定的数据之间的关联是通过“ID”来完成。下面是我们的百度天气里的preview的实现:

  preview: function(result, action_metadata) {
                    return new scopes.lib.PreviewQuery(
                                result,
                                action_metadata,
                                // run
                                function(preview_reply) {
                                    var layout1col = new scopes.lib.ColumnLayout(1);
                                    var layout2col = new scopes.lib.ColumnLayout(2);
                                    var layout3col = new scopes.lib.ColumnLayout(3);
                                    layout1col.add_column(["imageId", "headerId", "temperatureId", "windId"]);

                                    layout2col.add_column(["imageId"]);
                                    layout2col.add_column(["headerId", "temperatureId", "windId"]);

                                    layout3col.add_column(["imageId"]);
                                    layout3col.add_column(["headerId", "temperatureId", "windId"]);
                                    layout3col.add_column([]);

                                    preview_reply.register_layout([layout1col, layout2col, layout3col]);

                                    var header = new scopes.lib.PreviewWidget("headerId", "header");
                                    header.add_attribute_mapping("title", "title");
                                    header.add_attribute_mapping("subtitle", "subtitle");

                                    var image = new scopes.lib.PreviewWidget("imageId", "image");
                                    image.add_attribute_mapping("source", "art");

                                    var temperature = new scopes.lib.PreviewWidget("temperatureId", "text");
                                    temperature.add_attribute_mapping("text", "temperature");

                                    var wind = new scopes.lib.PreviewWidget("windId", "text");
                                    wind.add_attribute_mapping("text", "wind");

                                    preview_reply.push([image, header, temperature, wind ]);
                                    preview_reply.finished();
                                },
                                // cancelled
                                function() {
                                });
                }

我们可以运行我们的Scope:

 



我们可以通过如下的方式来把我们的Scope部署到我们的手机上:




    


对于想学习department的Scope的开发者来说,可以观看我们的培训视频地址.视频中的项目源码.Youtube视频链接
为了能够编译好连接中的例程,我们必须进入到我们的项目中,并安装如下的方法安装github:

$ bzr branch lp:~davidc3/+junk/github-js-scope
$ liuxg@liuxg:~/scope/github-js-scope/src$ unity-js-scopes-tool install ./node_modules github 




   

作者:UbuntuTouch 发表于2016/1/18 15:25:35 原文链接
阅读:221 评论:0 查看评论

Read more
UbuntuTouch

[原]浅析QML语言中的Qt.resolvedUrl

我看过很多的Qt代码,里面有时会用到Qt.resolvedUrl.有时候不仔细想,还真是一知半解.看了Qt的文档

url resolvedUrl(url url)

Returns url resolved relative to the URL of the caller.

你可能还会是一头雾水.这样吧,我们还是利用一个简单的例程来说们问题:


        Image {
            anchors.fill: parent
            source: "images/girl.jpg"

            Component.onCompleted: {
                // This prints 'false'. Although "pics/logo.png" was the input string,
                // it's been converted from a string to a URL, so these two are not the same.
                console.log(source == "images/girl.jpg")

                // This prints 'true' as Qt.resovledUrl() converts the string into a
                // URL with the correctly resolved path
                console.log("resolvedurl: " + Qt.resolvedUrl("images/girl.jpg"))
                console.log(source == Qt.resolvedUrl("images/girl.jpg"))

                // This prints the absolute path, e.g. "file:///path/to/pics/logo.png"
                console.log(source.toString())
            }
        }

上面的例程中,我们在Image中显示另一个女孩的照片.从代码中可以看出来,它明显使用的是相对路径.虽然我们输入的是相对路径,当它被输入到一个url的类型的属性时(比如Image中的source),它将被转换为一个QUrl的对象.如果我们直接把url中的内容和我们输入的内容相比较的话,就会失败.比如上面的代码的输出结果是:




Starting /usr/ubuntu-sdk-dev/bin/qmlscene...
qml: false
qml: resolvedurl: file:///home/liuxg/qml/resolveurl/images/girl.jpg
qml: true
qml: file:///home/liuxg/qml/resolveurl/images/girl.jpg

从上面的代码中可以看出来,使用Qt.resolvedUrl可以把我们的相对路径的url转换为觉得路径的path.

整个项目的源码在:https://gitcafe.com/ubuntu/resolveurl





            
作者:UbuntuTouch 发表于2016/1/25 16:24:22 原文链接
阅读:140 评论:0 查看评论

Read more
UbuntuTouch

在我们写QML应用时,我们如何来优化我们的应用呢?在Ubuntu平台的API中,有一个API叫做"PerformanceOverlay".就像它的名字所说的,它是一个overlay.它可以用来显示一个应用启动或运行时所需要的时间及CPU的使用情况.我们下面来用一个小的应用来测试一下:


import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.PerformanceMetrics 0.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "performanceoverlay.liu-xiao-guo"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(60)
    height: units.gu(85)

    PerformanceOverlay {
        active: true
    }

    Page {
        title: i18n.tr("PerformanceOverlay")

        Column {
            spacing: units.gu(1)
            anchors {
                margins: units.gu(2)
                fill: parent
            }

            Label {
                id: label
                objectName: "label"

                text: i18n.tr("Hello..")
            }

            Button {
                objectName: "button"
                width: parent.width

                text: i18n.tr("Tap me!")

                onClicked: {
                    label.text = i18n.tr("..world!")
                }
            }
        }
    }
}


当我们运行我们的应用时,在我们的应用的上面显示一个overlay.它是一个漂浮的窗口,我们可以用我们的手指来拖动它,以显示更好的效果.



在上面的图中,我们可以看出CPU的使用率,同时,当我们点击"Tap me"按钮时所显示需要的时间.如果显示为红色,它意味着我们需要做以下事情来优化我们的应用.

所有的源码在https://github.com/liu-xiao-guo/performanceoverlay




作者:UbuntuTouch 发表于2016/1/26 12:07:05 原文链接
阅读:128 评论:0 查看评论

Read more
UbuntuTouch

[原]如何实现QML中的pathview

在之前的很多练习及教程中,我们展示了如何在QML语言设计中使用ListViewGridView来展示我们所需要的效果.在今天的教程中,我们来深刻体会一下如何使用QML语言中的PathView来展示我们的效果.在PathView中,我们可以用它来显示旋转木马的效果.如果大家有使用我们的Ubuntu Scope的话,可能大家已经曾经使用carousel显示模板.在很多的场合中可以实现很炫的显示效果.


一个简单的实验

我们只打入如下的代码:

import QtQuick 2.0
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "carousel0.liu-xiao-guo"

    property int pathMargin: units.gu(10)

    width: units.gu(60)
    height: units.gu(85)

    Page {
        title: i18n.tr("carousel0")

        PathView {
            id: view
            anchors.fill: parent
            model: 32
            delegate: Text { text: index }

            path: Path {
                startX: 0
                startY: pathMargin
                PathLine { x: view.width; y: pathMargin }
            }
        }
    }
}

我们只使用了上面一些简单的代码.在这里,我们没有使用什么特别的model,我们只定义了一个简单的PathLine:


 PathLine { x: view.width; y: pathMargin }

这是一条从做到右的直线.我们的delegate也相对比较简单,我们只显示了每个项的index.运行我们的应用结果如下:

 

我们可以在上面进行左右的滑动,并看见数字可以在左右平滑地滑动.由于显示的效果没什么特别的,所以没有特别感觉到上面惊人的地方.我们通过这个例子对PathView有一个感性的认识.代码在地址:https://gitcafe.com/ubuntu/carousel0


加入我们的照片


我们可以在地址下载一些小的图标,并存于我们的项目中的一个叫做icons的目录中.为了能够在我们的例程中使用这些图片,我们创建了一个叫做Model0.qml的文件:

Model0.qml

import QtQuick 2.0

ListModel {
 ListElement { title: "Calendar"; iconSource: "icons/calendar.png" }
 ListElement { title: "Setup"; iconSource: "icons/develop.png" }
 ListElement { title: "Internet"; iconSource: "icons/globe.png" }
 ListElement { title: "Messages"; iconSource: "icons/mail.png" }
 ListElement { title: "Music"; iconSource: "icons/music.png" }
 ListElement { title: "Call"; iconSource: "icons/phone.png" }
 ListElement { title: "PodCast"; iconSource: "icons/podcast.png" }
 ListElement { title: "Recycle"; iconSource: "icons/recycle.png" }
}

同时也把我们的Main.qml修改为:

Main.qml

import QtQuick 2.0
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "carousel0.liu-xiao-guo"

    property int pathMargin: units.gu(10)

    width: units.gu(60)
    height: units.gu(85)

    Page {
        title: i18n.tr("carousel0")

        PathView {
            id: view
            width: parent.width
            height: parent.height*.2
            model: Model0 {}
            delegate: Item {
                id: wrapper
                width: parent.width/4
                height: width

                Image {
                    width: parent.width*.5
                    height: width
                    source: iconSource
                }
            }
            path: Path {
                startX: 0
                startY: pathMargin
                PathLine { x: view.width; y: pathMargin }
            }
        }
    }
}

在这里,我们使用了Model0.qml中定义的数据,我们同时也修改了delegate部分来显示相应的图片.运行我们的应用:

  

我们可以在上面的图片中滑动,并可以看见图片从做到右或从右到左的移动.我们可以使用这个效果来做一些菜单等.


加入我们的特效

在上面的例程中,我们虽然能够显示我们所需要的PathView,但是总体来说没有什么特效.如果细心的开发者可以看到在我们的Ubuntu Scope中,Carsousel中的图片有大有小,下面,我们重新改写我们的例程如下:

Main.qml

import QtQuick 2.0
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "carousel.liu-xiao-guo"

    property int pathMargin: units.gu(10)

    width: units.gu(60)
    height: units.gu(85)

    Page {
        title: i18n.tr("carousel")

        PathView {
            id: view
            width: parent.width
            height: parent.height*.2
            model: Model0 {}
            delegate: Item {
                id: wrapper
                width: parent.width/4
                height: width
                scale: PathView.scale
                Image {
                    width: parent.width*.5
                    height: width
                    source: iconSource
                }
            }
            path: Path {
                startX: 0
                startY: pathMargin
                PathAttribute { name: "scale"; value: 0.3 }
                PathLine { x: view.width/4; y: pathMargin }
                PathAttribute { name: "scale"; value: 0.6 }
                PathLine { x: view.width*2/4; y: pathMargin }
                PathAttribute { name: "scale"; value: 1.0 }
                PathLine { x: view.width*3/4; y: pathMargin }
                PathAttribute { name: "scale"; value: 0.6 }
                PathLine { x: view.width*4/4; y: pathMargin }
                PathAttribute { name: "scale"; value: 0.3 }
            }
        }

    }
}

在上面的例程中,我们多创建了几个PathLine,同时在每个PathLine中,我们同时加入一个叫做PathAttribute的属性.比如:

  PathAttribute { name: "scale"; value: 0.3 }

通过上面的定义,我们额外地定义了一些属性.注意这里的名字scale可以是你自己喜欢的名字.我们可以在我们的delegate中进行使用它:

            delegate: Item {
                id: wrapper
                width: parent.width/4
                height: width
                scale: PathView.scale
                Image {
                    width: parent.width*.5
                    height: width
                    source: iconSource
                }
            }

在上面我们定义了一个额外的scale属性.这样它就可以对我们的每个图片定制自己的大小.重新运行我们的应用:

 

整个项目的源码在: https://gitcafe.com/ubuntu/carousel2


利用PathQuad制作特效


我们上面所使用的都是PathLine.我们也可以使用PathQuad来制作我们特别想要的一些效果:

        PathView {
            id: view1
            // anchors.fill: parent
            width: parent.width
            height: parent.height*0.8
            anchors.top: view.bottom

            model: Model1 {}
            delegate: mydelegate
            path: Path {
                startX: view1.width/2; startY: 2* view1.height / 3;
                PathAttribute { name: "opacity"; value: 1 }
                PathAttribute { name: "scale"; value: 1 }
                PathAttribute { name: "z"; value: 100 }
                PathQuad { x: view1.width/2; y: view1.height / 3; controlX: view1.width+200; controlY: view1.height/2}
                PathAttribute { name: "opacity"; value: 0.3 }
                PathAttribute { name: "scale"; value: 0.5 }
                PathAttribute { name: "z"; value: 0 }
                PathQuad { x: view1.width/2; y: 2*view1.height / 3; controlX: -200; controlY: view1.height/2}
            }
        }

运行我们的应用:


  

整个项目的源码在:https://gitcafe.com/ubuntu/carousel3

作者:UbuntuTouch 发表于2016/1/28 15:52:10 原文链接
阅读:144 评论:0 查看评论

Read more
UbuntuTouch

在前面的文章“如何在QML中使用ListView并导航到其它页面中”中,我们已经介绍了各种在ListView中导航到其它页面的方法。在这篇文章中,我来介绍如何建立一个expandable的ListView。通过这样的方法,ListView可以不用导航到其它的页面中,但是它可以通过状态的控制占据整个页面,而得到显示。


首先我们可以使用Ubuntu SDK来创建一个最简单的“QML App with Simple UI (qmlproject)”项目。我们的Main.qml非常简单:

Main.qml

import QtQuick 2.4
import Ubuntu.Components 1.2

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "expandinglist.liu-xiao-guo"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
//    useDeprecatedToolbar: false

    width: units.gu(60)
    height: units.gu(85)

    Page {
        id: mainpage
        title: i18n.tr("expandinglist")
        flickable: null

        ListView {
            id: listView
            anchors.fill: parent
            clip: true
            model: RecipesModel {}
            delegate: RecipesDelegate {}
        }
    }
}


就像上面的代码显示的那样,我们需要一个model。为此,我们创建了如下的RecipesModel.qml文件:

RecipesModel.qml


import QtQuick 2.0

ListModel {
    ListElement {
        title: "Pancakes"
        picture: "content/pics/pancakes.jpg"
        ingredients: "<html>
                       <ul>
                        <li> 1 cup (150g) self-raising flour
                        <li> 1 tbs caster sugar
                        <li> 3/4 cup (185ml) milk
                        <li> 1 egg
                       </ul>
                      </html>"
        method: "<html>
                  <ol>
                   <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
                   <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
                   <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
                   <li> Turn over and cook other side until golden.
                  </ol>
                 </html>"
    }
    ListElement {
        title: "Fruit Salad"
        picture: "content/pics/fruit-salad.jpg"
        ingredients: "* Seasonal Fruit"
        method: "* Chop fruit and place in a bowl."
    }
    ListElement {
        title: "Vegetable Soup"
        picture: "content/pics/vegetable-soup.jpg"
        ingredients: "<html>
                       <ul>
                        <li> 1 onion
                        <li> 1 turnip
                        <li> 1 potato
                        <li> 1 carrot
                        <li> 1 head of celery
                        <li> 1 1/2 litres of water
                       </ul>
                      </html>"
        method: "<html>
                  <ol>
                   <li> Chop vegetables.
                   <li> Boil in water until vegetables soften.
                   <li> Season with salt and pepper to taste.
                  </ol>
                 </html>"
    }
    ListElement {
        title: "Hamburger"
        picture: "content/pics/hamburger.jpg"
        ingredients: "<html>
                       <ul>
                        <li> 500g minced beef
                        <li> Seasoning
                        <li> lettuce, tomato, onion, cheese
                        <li> 1 hamburger bun for each burger
                       </ul>
                      </html>"
        method: "<html>
                  <ol>
                   <li> Mix the beef, together with seasoning, in a food processor.
                   <li> Shape the beef into burgers.
                   <li> Grill the burgers for about 5 mins on each side (until cooked through)
                   <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
                  </ol>
                 </html>"
    }
    ListElement {
        title: "Lemonade"
        picture: "content/pics/lemonade.jpg"
        ingredients: "<html>
                       <ul>
                        <li> 1 cup Lemon Juice
                        <li> 1 cup Sugar
                        <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
                       </ul>
                      </html>"
        method: "<html>
                  <ol>
                   <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
                   <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
                   <li> Chill or serve over ice cubes.
                  </ol>
                 </html>"
    }
}



在这里,我们可以看到在文字中,我们可以使用html格式来格式化我们的文字。这对我们多样的显示是非常有用的。


我们最关键的设计在于RecipesDelegate.qml文件:

RecipesDelegate.qml

import QtQuick 2.0
import Ubuntu.Components 1.2

// Delegate for the recipes.  This delegate has two modes:
    // 1. List mode (default), which just shows the picture and title of the recipe.
    // 2. Details mode, which also shows the ingredients and method.
//Component {
//    id: recipeDelegate
//! [0]
    Item {
        id: recipe

        // Create a property to contain the visibility of the details.
        // We can bind multiple element's opacity to this one property,
        // rather than having a "PropertyChanges" line for each element we
        // want to fade.
        property real detailsOpacity : 0
//! [0]
        width: ListView.view.width
        height: units.gu(10)

        // A simple rounded rectangle for the background
        Rectangle {
            id: background
            x: 2; y: 2; width: parent.width - x*2; height: parent.height - y*2
            color: "ivory"
            border.color: "orange"
            radius: 5
        }

        // This mouse region covers the entire delegate.
        // When clicked it changes mode to 'Details'.  If we are already
        // in Details mode, then no change will happen.
//! [1]
        MouseArea {
            anchors.fill: parent
            onClicked: {
                console.log("recipe.y: " + recipe.y );
                console.log("origin.y: " + listView.originY );
                recipe.state = 'Details';
            }
        }

        // Lay out the page: picture, title and ingredients at the top, and method at the
        // bottom.  Note that elements that should not be visible in the list
        // mode have their opacity set to recipe.detailsOpacity.

        Row {
            id: topLayout
            x: 10; y: 10; height: recipeImage.height; width: parent.width
            spacing: 10

            Image {
                id: recipeImage
                width: units.gu(8); height: units.gu(8)
                source: picture
            }
//! [1]
            Column {
                width: background.width - recipeImage.width - 20; height: recipeImage.height
                spacing: 5

                Text {
                    text: title
                    font.bold: true; font.pointSize: units.gu(2)
                }

                SmallText {
                    text: "Ingredients"
                    font.bold: true
                    opacity: recipe.detailsOpacity
                }

                SmallText {
                    text: ingredients
                    wrapMode: Text.WordWrap
                    width: parent.width
                    opacity: recipe.detailsOpacity
                }
            }
        }

//! [2]
        Item {
            id: details
            x: 10; width: parent.width - 20

            anchors { top: topLayout.bottom; topMargin: 10; bottom: parent.bottom; bottomMargin: 10 }
            opacity: recipe.detailsOpacity
//! [2]
            SmallText {
                id: methodTitle
                anchors.top: parent.top
                text: "Method"
                font.pointSize: 12; font.bold: true
            }

            Flickable {
                id: flick
                width: parent.width
                anchors { top: methodTitle.bottom; bottom: parent.bottom }
                contentHeight: methodText.height
                clip: true

                Text { id: methodText; text: method; wrapMode: Text.WordWrap; width: details.width }
            }

            Image {
                anchors { right: flick.right; top: flick.top }
                source: "content/pics/moreUp.png"
                opacity: flick.atYBeginning ? 0 : 1
            }

            Image {
                anchors { right: flick.right; bottom: flick.bottom }
                source: "content/pics/moreDown.png"
                opacity: flick.atYEnd ? 0 : 1
            }
//! [3]
        }

        // A button to close the detailed view, i.e. set the state back to default ('').
        TextButton {
            y: 10
            anchors { right: background.right; rightMargin: 10 }
            opacity: recipe.detailsOpacity
            text: "Close"

            onClicked: recipe.state = '';
        }

        states: State {
            name: "Details"

            PropertyChanges { target: background; color: "white" }
            PropertyChanges { target: recipeImage; width: 130; height: 130 } // Make picture bigger
            PropertyChanges { target: recipe; detailsOpacity: 1; x: 0 } // Make details visible
            PropertyChanges { target: recipe; height: listView.height } // Fill the entire list area with the detailed view

            // Move the list so that this item is at the top.
            PropertyChanges { target: recipe.ListView.view; explicit: true;
                contentY: {
                    console.log("listView.contentY: " + listView.contentY);
                    return recipe.y + listView.contentY;
                }
            }

            // Disallow flicking while we're in detailed view
            PropertyChanges { target: recipe.ListView.view; interactive: false }
        }

        transitions: Transition {
            // Make the state changes smooth
            ParallelAnimation {
                ColorAnimation { property: "color"; duration: 500 }
                NumberAnimation { duration: 300; properties: "detailsOpacity,x,contentY,height,width" }
            }
        }
//    }
//! [3]
}


在这个delegate里,它有两个状态:

  • 默认的List模式。在这种模式下,它只显示一个图片及title
  • 详细模式。在这种模式下,除了显示上面的图片和title以外,还显示model中的ingredients及method
在详细模式下的状态为:

       states: State {
            name: "Details"

            PropertyChanges { target: background; color: "white" }
            PropertyChanges { target: recipeImage; width: 130; height: 130 } // Make picture bigger
            PropertyChanges { target: recipe; detailsOpacity: 1; x: 0 } // Make details visible
            PropertyChanges { target: recipe; height: listView.height } // Fill the entire list area with the detailed view

            // Move the list so that this item is at the top.
            PropertyChanges { target: recipe.ListView.view; explicit: true;
                contentY: {
                    console.log("listView.contentY: " + listView.contentY);
                    return recipe.y + listView.contentY;
                }
            }

            // Disallow flicking while we're in detailed view
            PropertyChanges { target: recipe.ListView.view; interactive: false }
        }

在这里,一定要注意:

            PropertyChanges { target: recipe.ListView.view; explicit: true;
                contentY: {
                    console.log("listView.contentY: " + listView.contentY);
                    return recipe.y + listView.contentY;
                }
            }

可以帮我们把当前的项移到ListView的窗口中。

我们运行我们的应用:

    

在上面的第二个图中,点击“Close”按钮,就可以回到List模式。

整个项目的代码在:git clone https://gitcafe.com/ubuntu/expandinglist.git


作者:UbuntuTouch 发表于2015/6/5 9:37:23 原文链接
阅读:679 评论:0 查看评论

Read more
UbuntuTouch

[原]Ubuntu OS系统融合(英文视频)

在这个视频里,我们可以看见Ubuntu系统在不断地演进。在未来手机,平板,电视及桌面将使用一个操作系统。Ubuntu手机操作系统正在为这一切做准备。


http://v.youku.com/v_show/id_XOTA5NDA0OTUy.html

作者:UbuntuTouch 发表于2015/3/11 13:26:59 原文链接
阅读:645 评论:0 查看评论

Read more
UbuntuTouch

[原]Ubuntu 手机开发培训准备

在这篇文章中,我们将介绍学生如何做培训准备前的准备工作。提前准备并安装好自己的环境是做好一个培训非常重要的步骤。否则我们将浪费我们自己很多的宝贵的时间在课堂上!


                 

1)安装好自己的SDK


如果想在自己的电脑上安装Ubntu系统

学生可以按照文章“Ubuntu SDK 安装”安装好自己的Ubuntu系统及SDK。让后根据文章“创建第一个Ubuntu for phone应用”来检验自己安装的环境是否正确。这种安装通常需要在电脑上安装多个系统,或虚拟机(模拟器在虚拟机的效果可能并不好,在虚拟机中模拟器目前不能正常启动)。

如果想做一个专为Ubuntu手机开发而做的Live USB

请参照文章“如何制作Ubuntu SDK Live USB盘”来专门制作一个可以启动的Live USB盘。这个盘可以直接插入到电脑中的USB口中,并启动Ubuntu系统。这个USB盘中已经安装好整个可以供开发的SDK,不需要安装任何额外的软件即可开发。

a) 在BIOS中启动硬件虚拟化功能,这样会使得模拟器的运行速度加快
b) 在BIOS中设置优选顺序以使得USB可以优先启动,或在启动的时候按下F12功能键,并选择由USB来启动Ubuntu

在启动Ubuntu系统后,Ubuntu SDK已经完全安装好了。开发者可以直接进行开发了。建议参阅文章“创建第一个Ubuntu for phone应用”来检验自己安装的环境是否正确。

在开发过程中如果使用手机进行安装时,如果需要密码解锁手机的话,这个密码是“0000”。模拟器的默认密码也是“0000”。

2)Ubuntu手机介绍


对不熟悉Ubuntu手机的开发者来说,可以先观看视频“如何使用Ubuntu手机”来了解Ubuntu手机。如果你想对Ubuntu SDK有更深的认识,请观看视频“如何使用Ubuntu SDK (视频)”。开发者也可以观看Ubuntu手机的官方宣传视频来更进一步了解。

你可以在地址“Ubuntu手机介绍”下载有关Ubuntu手机介绍的幻灯片,并在地址观看相应的视频


3)QML应用开发


你如果是一个入门级的开发者,我建议你先看看我们的入门级的教程:
通过这几个小的练习,你可以对QML语言的设计有一个初步的了解。

Flickr应用开发

阅读文章“使用Ubuntu SDK开发Flickr应用教程”,并观看视频“Ubuntu手机应用QML开发 (视频)”。幻灯片“Ubuntu应用开发”及幻灯片的培训视频

教程的源码在: bzr branch lp:~liu-xiao-guo/debiantrial/flickr7
我们可以在Shell中输入以上的指令来下载源码。

DeveloperNews RSS阅读器

首先我们可以阅读文章“从零开始创建一个Ubuntu应用--一个小的RSS阅读器”及文章“如何在Ubuntu中使用条件布局”。视频在“在Ubuntu平台上开发Qt Quick QML应用 (视频)”。在线培训视频

教程的源码在:bzr branch lp:~liu-xiao-guo/debiantrial/developernews4

我们可以在Shell中输入以上的指令来下载源码。

用Ubuntu SDK创建Currency Converter (视频)

网址也有很多的教程哦!


4)Scope 开发


大家可以先观看视频“Ubuntu Scope简介及开发流程”来了解Ubuntu OS上的Scope开发流程。

阅读文章“在Ubuntu OS上创建一个dianping Scope (Qt JSON)”,并观看视频“如何在Ubuntu OS上开发Scope (视频)”。教程的另外一个视频在地址观看。

幻灯片“Scope技术开发”。幻灯片讲演的视频在地址观看。

教程的源码在: bzr branch lp:~liu-xiao-guo/debiantrial/dianpianclient8
我们可以在Shell中输入以上的指令来下载源码。

更多关于Scope开发的例程可以在链接找到。

- 如果你想开发一个department的Scope,请参阅文章“在Ubuntu OS上创建一个department 点评Scope (Qt XML)
- 如果你对go语言比较熟悉,你可以“使用golang来设计我们的Ubuntu Scope”。
- 如果你想对你的搜索的结果进行过滤,你可以参阅文章“如何在Ubuntu Scope中利用Filter来更加精准地提高搜索的质量

5)HTML 5开发


我们可以参阅文章“在Ubuntu手机平台上创建一个HTML 5的应用”来学习如何在Ubuntu平台上开发HTML 5的应用。源码在地址下载:

git clone https://gitcafe.com/ubuntu/html-rssreader6.git

Ubuntu上的HTML5开发幻灯片:Ubuntu上的HTML5开发。幻灯片视频

大家可以利用在线Webapp生成器来生产我们喜欢的网页的click安装包。具体教程“如何使用在线Webapp生成器生成安装包

大家如果对Cordova HTML的开发比较感兴趣,可以学习教程“在Ubuntu平台上创建Cordova Camera HTML5应用

更多例程:
  • 百度翻译: bzr branch lp:~liu-xiao-guo/debiantrial/baidutranslator
  • 字典: bzr branch lp:~liu-xiao-guo/debiantrial/meanings

6)更多的培训材料


我们也有更多的英文的培训材料。开发者可以在地址下载。

如果您的英文足够好,你可以向我们的技术支持mailinglist: ubuntu-phone@lists.launchpad.net发去你的问题。全球的开发者可以帮忙回到你的问题。


如果有任何问题,请在该文章处评论。我会尽力回答你们的问题。大家也可以到Ubuntu手机专有讨论区来讨论问题




对于英文比较好的开发者来说,可以访问网址askubuntu.com来获取更多的信息,或者订购我们的ubuntu应用开发mailinglist

另外,开发者也可以使用IRC上freenode上的channel: #ubuntu-app-devel及#ubuntu-touch来参与讨论以得到答案.



在现场教学中的过程中如果需要联网,请使用如下的用户名及密码

手机的解锁密码为:0000

另外,我们有一个技术支持及讨论的QQ群:391093791.我们的官方微博地址:http://weibo.com/officialubuntu

刘老师微博:老刘就是老牛



作者:UbuntuTouch 发表于2015/1/4 15:36:54 原文链接
阅读:6569 评论:6 查看评论

Read more
UbuntuTouch

在这篇文章中,我们来介绍如何判断一个QML应用被推到后台或前台。我们知道,在Ubuntu手机平台中,它是一个单应用的操作系统。当一个应用被推到后台后,应用就被挂起,不能运行。我们有时需要这个标志来判断我们的应用什么时候是在前台,什么时候是在后台。


我们用Ubuntu SDK创建一个简单的QML应用:


import QtQuick 2.0
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    id: main
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "com.ubuntu.developer.liu-xiao-guo.foregrounddetect"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(100)
    height: units.gu(75)


    Page {
        title: i18n.tr("ForegroundDetect")

        Connections {
             target: Qt.application
             onActiveChanged: {
                 console.log("Qt.application.active: " + Qt.application.active);
             }
         }
    }
}

在这里,我们使用Qt.application这个变量的"active"属性来判断一个应用是否被推到后台或前台。我们运行应用结果如下:




当我们在手机上把应用推到后台时,就会显示false;当我们把应用推到前台时,就会显示true。

整个应用的源码在:bzr branch lp:~liu-xiao-guo/debiantrial/foregrounddetect


作者:UbuntuTouch 发表于2015/1/5 10:56:25 原文链接
阅读:1023 评论:0 查看评论

Read more
UbuntuTouch

在这个视频里,我们从“0”开始来开发一个mini的RSS阅读器。通过这个练习,开发者可以对QML的编程有一个基本的了解,并了解在Ubuntu平台上的一些开发的流程。应用的图片如下:


  



作者:UbuntuTouch 发表于2015/1/13 15:08:31 原文链接
阅读:885 评论:0 查看评论

Read more
UbuntuTouch

对于一些想开发Ubuntu手机应用或Scope的开发者来说,不想重新买一个电脑安装Ubuntu操作系统或在自己的硬盘上重新安装一个Ubuntu系统,那么可以考虑制作一个Ubuntu系统的Live USB盘。这个USB包括如下的部分:


  • Ubuntu Kylin 15.04 操作系统
  • Ubuntu SDK (包括已经安装好的SDK,模拟器及编译环境)

使用这个Live USB盘,开发者就不用安装任何的东西,直接插入电脑的USB口中。在电脑启动的过程中,选择我们制作好的USB启动盘进行启动(在电脑启动的过程中,按下“F12”键)。在启动的过程中选择“Try Ubuntu Kylin without installing




虽然这是一个Ubuntu OS的启动盘,但是它可以保存我们在开发过程中所创建的项目(存于Home目录中)及一些设置(比如wifi设置密码等)。


当我们选择USB时,我们最好是选择USB 3.0并把USB盘放入到电脑USB 3.0的口中。一般来说,电脑上的USB 3.0口是用蓝色标示的。建议使用质量较好,速度较快一点的USB这样可以使得系统的启动和运行更快更流畅。目前我们使用SanDisk CZ80来做测试,效果还是不错的。USB需要有16G的存储。


为了使得我们的模拟器能够更加流畅及模拟器不会出现黑色的屏幕,我们需要在电脑的BIOS里启动硬件虚拟化功能。开发者需要到自己的电脑的BIOS里的设置启动VT-X/AMD-V。开发者可以参考文章“Ubuntu SDK 安装”来检查自己的电脑是否支持virtualization。




如果开发者想要在自己的电脑上安装Ubuntu系统并在上面开发的话,可以参考文章“Ubuntu SDK 安装”来一步一步地安装Ubuntu SDK。



1)如何在Ubuntu系统下制作Live USB盘


启动Ubuntu操作系统,打开浏览器并在如下的地址下载最新的image:


http://pan.baidu.com/s/1AXioQ#path=%252Fkylin-usb-vivid-gm-1


下载的文件包含:

  • kylin-live-20150612-1-vivid-GM1-amd64.iso (md5sum 8b19282e3bb7f21c0229f767290039fe) 
  • casper-rw-20150612-1.tgz  (md5sum cf8e205d2aa1722b00acb4da0b8257db )
  • md5sum (md5sum 说明文件,方便检查下载后检查对不对)

我们把下载的文件存于到我们想要的一个目录中,比如在自己的Home下的“usb”目录中。


在Dash中输入“usb”,并启动“Startup Disk Creator/启动盘创建器”






我们按照如下的方法来制作我们的USB启动盘。




注意上面图中的Source disk image (.iso)文件的名称根据不同的发布版本,会有不同。




在设置“储存在额外保留空间”时,它的值应该为非零的值。等USB盘已经制作好以后,你将会看到如下的画面:







重新挂载USB盘,因为在前一步会自动卸载USB盘,或者在Ubuntu中的文件浏览器中点击USB所在的device。这样就可以完成重新挂载USB:





然后按下面运行自带的脚本,参数为 USB 盘挂载的路径。


解压已经下载的casper-rw-2015xxxx-1.tgz文件




等文件都被解压完后(比如解压到home目录下的一个叫做usb的目录),进入解压文件所在的目录,并在shell中执行如下的指令:


liuxg@liuxg:~/usb$ ./post-usb-creator-linux.sh /media/liuxg/BD52-7153/


这里“/liuxg/BD52-7153”为USB盘挂载的路径。根据自己USB盘所在的路径替换。


2)如何在Windows 平台下制作启动盘


http://www.ubuntu.com/download/desktop/create-a-usb-stick-on-windows

下载制作工具,与 Linux 平台的工具相似。




注意这里的“Step 2”中,根据发布版本的不同,.iso文件名字会有差别。 当我们在选择“Persistent file”时,它的大小应该是非零的一个值。在我们填入“Step 2”时,我们不应该把拷贝好的字符串拷到该输入框中,否则在“Step 3”中的输入框就会是灰色的。我们应该点击“Browse”按钮,并按照如下的方式进行输入image的路径:




解压已经下载的casper-rw-2015xxxx.tgz文件,并解压后的casper-rw文件拷贝到USB盘的主目录下:





:如果只想使用英文版的Ubuntu系统就不需要进行下面的步骤。如果想要支持中文版,请把 post-usb-creator-window.sh 也拷贝到 USB盘的根目录下。从USB 盘启动Ubuntu系统后, 在dash中启动Terminal,






并在Terminal中执行如下的命令:


$ cd /cdrom/

$ sudo ./post-usb-creator-window.sh


再次重新启动后,会进入中文版的Ubuntu系统。


3)测试已经制作好的USB启动盘


我们可以把我们的Live USB盘插入电脑,我们可以通文章“创建第一个Ubuntu for phone应用”来检验我们是否有一个完好的Ubuntu SDK。


在我们启动模拟器时,如果需要输入密码,请使用默认的密码“0000”。如果开发者需要自己修改这个密码,请到Ubuntu SDK模拟器中的“系统设置”中去修改。


对于应用开发者来说,在Qt Creator中的热键组合“Ctrl + Space”键有它独特的用处。可是,在Ubuntu系统中,“Ctrl + Space”被用来转换中英文输入法。建议开发者参考文章“怎么在Ubuntu OS上面安装搜狗输入法及对Qt Creator的支持”来重新定义键的组合。


已知问题 (known issues)

如果你在使用的过程中,发现有如下的乱码的情况(极少情况下出现),请重新启动你的机器来纠正这个问题。





作者:UbuntuTouch 发表于2015/1/22 15:35:55 原文链接
阅读:2004 评论:0 查看评论

Read more
UbuntuTouch

[原]Windows7下安装Ubuntu双系统

Windows7和Ubuntu双系统的安装是非常容易的。在Ubuntu的安装的时候,已经提供了图形化的界面来帮助用户安装。你可以选择单单安装Ubuntu操作系统抹去原来的Windows操作系统,也可以选择与Windows操作系统共存,用Windows引导Ubuntu。但是这就造成了一个问题——一旦你想要删除Ubuntu操作系统,想要抹掉原先分给Ubuntu的磁盘空间,就会破坏Windows的MBR分区。因为在你按照原先系统安装盘的指令安装Ubuntu操作系统的时候,MBR分区的数据会被重写。

小编之前也有过这样的情况。后果就是在我删除整个Ubuntu分区后,windows也已经打不开了。在这个时候,其实你可以做一个工作来找回你“丢失”的Windows操作系统。修复MBR分区。比较常见的,比较“古朴”的方法就是进DOS使用fdisk /mbr命令。但是当时小编用的时候貌似还是不行。于是找到了以下的方法:进入windows系统,调出cmd,用bootrec /fixmbr命令,就能修复MBR分区了。

那么每次这样是不是很麻烦?能不能从源头上来解决呢?可以的。在安装Ubuntu操作系统的时候就可以解决这个问题。下面就跟着小编的这个步骤来安装操作系统,不破坏windows的正常使用。


1)下载Ubuntu desktop操作系统


可以在以下网址:http://www.ubuntu.com/download/desktop

下载到Ubuntu desktop的发行版。根据你自己的使用情况及CPU的情况来下载适合自己电脑的Ubuntu Desktop操作系统。




建议大家下载Ubuntu 14.10,因为在做Ubuntu手机、平板开发的时候是需要14.10的系统的。小编在这里选择64位的14.10操作系统



2)磁盘分区


在这一步中,你将要对你的磁盘进行分区。如果普通使用的话20G的磁盘空间就可以了,但是做开发的话是不够的。小编在这里给Ubuntu分了100G的空间。

在我的“计算机”上右键,选择“管理”,打开之后依次选择“存储——磁盘管理”,之后你就将看到你的硬盘的虚拟化的图像。其实还有其他的外接存储设备都会有显示。




在一个硬盘分区上右键选择“压缩卷”,跟着步骤走,输入你想要磁盘大小。


3)制作USB启动盘


找一个U盘,4G的吧,应该够了,插入电脑的USB接口。小编在这里使用的是UltraISO(http://cn.ultraiso.net/xiazai.html)这个软件。




“打开文件”,定位到你刚刚下载的Ubuntu的安装文件,“打开”




选择“启动”——“写入硬盘映像”




在这里一定要注意哦,这里“硬盘驱动器”这里是不是你的那个U盘。如果你插了其他的存储设备一定要看清,不然会造成不必要的损失。

然后点“写入”,静候直至出现“刻录成功”的字样。




至此,你的U盘安装盘就已经做好了。



4)安装Ubuntu操作系统


令人激动人心的时刻到了安装Ubuntu操作系统




开机的时候进入Boot Manager选择USB启动。各个电脑的进入Boot选项的方法都不同,但是无外乎F12,F10,F2等等的function键。




在这里你可以选择

  • 使用Ubuntu操作系统但并不安装

  • 安装Ubuntu

  • OEM安装

  • 检查磁盘

我们在这里选择“Install Ubuntu”(“安装Ubuntu”)


注:如果你看到以下画面,请:

  • 检查电脑USB口

  • 更换U盘重新制作USB启动盘

  • 插拔U盘查看是否是接触问题

最有可能的还是U盘的问题,所以请使用U盘芯片比较好的U盘,推荐用Sandisk





接着就是选择语言,wifi,等等的安装前的设置。

但是我们要注意一下,在安装类型的这里仔细看一下。








在这里需要注意下


安装类型选择其他选项




选择你刚刚在Windows下分出来的那个盘,选择“Ext4 日志文件系统” 挂载点“/”




这步做完,你的那个盘的格式会变为Ext4




然后在“安装启动引导器的设备”一栏里选择你的那个盘,小编这里是“sda6”(每个人的电脑可能显示的是不同的)




之后选择“格式化”——“现在安装”

在选择时区、设置用户名密码之后就会进入到安装过程




这一步之后就已经把Ubuntu安装到那个分区了。

电脑就会自动重启


5)设置引导


在如上步骤安装完之后,重启进入windows引导没有Ubuntu的。




在这一步就是要设置Ubuntu的引导。

进入windows之后,我们所使用的软件是EasyBCD(http://easybcd.softonic.cn/)





选择“Add New Entry”选择“Linux/BSD”——选择“GRUB2”并命名为Ubuntu,点击“Add Entry”





6)重新启动计算机,安装完成


重新启动计算机后,你就会看到Windows的引导里有你刚刚建立的Ubuntu的选项。选择Ubuntu就会进入Grub。然后就会进入Ubuntu操作系统。






这样的安装方式,就不怕以后删除Ubuntu之后不能启动windows了,但是小编还是希望大家不要删除Ubuntu的啦~


Ubuntu小编原创,欢迎转载!



作者:UbuntuTouch 发表于2015/4/8 8:53:44 原文链接
阅读:1306 评论:0 查看评论

Read more
UbuntuTouch

在这篇文章中,我们将介绍如何使用Ubuntu系统提供的online account API来实现我们的微博。通过这篇文章,开发者可以使用同样的方法来实现对其它Web Service的访问,比如淘宝,优酷等网站的访问。我们实现的新浪微博的Scope的截图如下。本篇文章的重点是介绍online account API的使用,所以我不会像以前的那些教程一样从最基本的Scope开发介绍。更多关于online account的介绍在网址找到。


   


1)创建一个最基本的weibo Scope

我们通过使用Ubuntu SDK来创建一个最基本的Scope。在这里我们使用如下的Scope template:


     


    

按照如上的步骤,我们可以创建一个我们自己的一个最基本的weibo Scope,虽然里面显示的还是天气。


2)为online account添加必要的文件


我们可以参考文章,也可以参照视频,来对online account API有一个更深的了解。为了方便我们的设计,我们在项目的根目录下创建如下的"click"目录:



我们同时也把在根目录下的“manifest.json.in”及“weibo.apparmor”移到“click”目录下,当然,我们也需要对根目录下的“CMakeLists.txt”做必要的修改。修改后的CMakeLists.txt文件如下:

project(weibo CXX)
cmake_minimum_required(VERSION 2.8.10)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")

# We require g++ 4.9, to avoid ABI breakage with earlier version.
set(cxx_version_required 4.9)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    if (NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${cxx_version_required}")
        message(FATAL_ERROR "g++ version must be ${cxx_version_required}!")
    endif()
endif()

# Set strict and naggy C++ compiler flags, and enable C++11
add_definitions(
  -fno-permissive
  -std=c++11
  -pedantic
  -Wall
  -Wextra
  -fPIC
  -DQT_NO_KEYWORDS
)

include(GNUInstallDirs)
find_package(PkgConfig)
find_package(Intltool)

# We depend on Boost for string trimming
find_package(
  Boost
  REQUIRED
)

# Search for our dependencies
pkg_check_modules(
  SCOPE
  libunity-scopes>=0.6.0
  net-cpp>=1.1.0
  REQUIRED
)

find_package(Qt5Core REQUIRED)
include_directories(${Qt5Core_INCLUDE_DIRS})

# Add our dependencies to the include paths
include_directories(
  "${CMAKE_SOURCE_DIR}/include"
  ${Boost_INCLUDE_DIRS}
  ${SCOPE_INCLUDE_DIRS}
)

# Do not remove this line, its required for the correct functionality of the Ubuntu-SDK
set(UBUNTU_MANIFEST_PATH "click/manifest.json.in" CACHE INTERNAL "Tells QtCreator location and name of the manifest file")
set(UBUNTU_PROJECT_TYPE "Scope" CACHE INTERNAL "Tells QtCreator this is a Scope project")

# Important project paths
set(CMAKE_INSTALL_PREFIX /)
set(SCOPE_INSTALL_DIR "/weibo")
set(GETTEXT_PACKAGE "weibo")
set(PACKAGE_NAME "weibo.ubuntu")
set(SCOPE_NAME "${PACKAGE_NAME}_weibo")

set(SCOPE_INSTALL_NAME "${PACKAGE_NAME}_weibo")
set(SCOPE_ACCOUNTS_NAME "${PACKAGE_NAME}_accounts")
set(SYMBOL_MAP "${CMAKE_SOURCE_DIR}/data/${PACKAGE_NAME}.map")

add_definitions(-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}")
add_definitions(-DSCOPE_NAME="${SCOPE_NAME}")
add_definitions(-DSCOPE_INSTALL_NAME="${SCOPE_INSTALL_NAME}")
add_definitions(-DSCOPE_ACCOUNTS_NAME="${SCOPE_ACCOUNTS_NAME}")
add_definitions(-DPACKAGE_NAME="${PACKAGE_NAME}")

# If we need to refer to the scope's name or package in code, these definitions will help

#This command figures out the target architecture and puts it into the manifest file
execute_process(
  COMMAND dpkg-architecture -qDEB_HOST_ARCH
  OUTPUT_VARIABLE CLICK_ARCH
  OUTPUT_STRIP_TRAILING_WHITESPACE
)

#configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)

# Install the click manifest
#install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json DESTINATION "/")
#install(FILES "weibo.apparmor" DESTINATION "/")

# Make these files show up in QtCreator
file(GLOB_RECURSE
  _PO_FILES
  "po/*.po" 
)
add_custom_target(hidden_files
  ALL
  SOURCES
#    manifest.json.in
#    weibo.apparmor
    data/${SCOPE_NAME}.ini.in
    po/POTFILES.in
    po/${GETTEXT_PACKAGE}.pot
    ${_PO_FILES}
)

add_subdirectory(click)

# Add our main directories
add_subdirectory(src)
add_subdirectory(data)
add_subdirectory(po)

# Set up the tests
enable_testing()
add_subdirectory(tests)
add_custom_target(
  check
  ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --output-on-failure
)

这里主要的修改是影藏显示“manifest.json.in”及“weibo.apparmor”文件的显示,应为这两个文件已经移到“click”目录中了。同时也注释掉如下的语句,应为这项工作在“click”目录中的“CMakeLists.txt”中已经做了。

#configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)

# Install the click manifest
#install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json DESTINATION "/")
#install(FILES "weibo.apparmor" DESTINATION "/")

另外,我们为了能够正确地显示项目,我们也对如下的句子做了修改:

set(UBUNTU_MANIFEST_PATH "click/manifest.json.in" CACHE INTERNAL "Tells QtCreator location and name of the manifest file")

这里我们加上了“click”路径。同时我们也加入了如下的定义:

set(SCOPE_INSTALL_NAME "${PACKAGE_NAME}_weibo")
set(SCOPE_ACCOUNTS_NAME "${PACKAGE_NAME}_accounts")
set(SYMBOL_MAP "${CMAKE_SOURCE_DIR}/data/${PACKAGE_NAME}.map")

add_definitions(-DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}")
add_definitions(-DSCOPE_NAME="${SCOPE_NAME}")
add_definitions(-DSCOPE_INSTALL_NAME="${SCOPE_INSTALL_NAME}")
add_definitions(-DSCOPE_ACCOUNTS_NAME="${SCOPE_ACCOUNTS_NAME}")
add_definitions(-DPACKAGE_NAME="${PACKAGE_NAME}")

这样这些变量及定义可以在项目的其它文件中被正确地引用了。

下面,我们来看看“click”目录下的文件:

apparmor.json


{
    "template": "ubuntu-scope-network",
    "policy_groups": [
        "accounts"
    ],
    "policy_version": 1.2
}


注意这里在“policy_groups”里我们多加入了一个称作为“accounts”的policy。这个是必须的,否则不可以正常工作。


manifest.json.in

这个文件的显示如下:

{
    "description": "This is a tutorial for weibo scope",
    "framework": "ubuntu-sdk-14.10",
    "architecture": "@CLICK_ARCH@",
    "hooks": {
        "weibo": {
            "scope": "weibo",
            "apparmor": "apparmor.json",
            "account-application": "weibo.application",
            "account-service": "weibo.service"
        },
        "accounts": {
            "account-provider": "weibo.provider",
            "account-qml-plugin": "qml-plugin"
        }
    },
    "maintainer": "XiaoGuo, Liu <xiaoguo.liu@canonical.com>",
    "name": "@PACKAGE_NAME@",
    "title": "weibo scope",
    "version": "0.1"
}

这个文件和我们template所产生的文件略有不同。这里的“hooks”中加入了account的一些东西。在每个用户登陆时都会生产相应的配置文件。

weibo.application.in


<?xml version="1.0" encoding="UTF-8"?>
<application>
  <description>Weibo scope</description>
  <desktop-entry>@SCOPE_INSTALL_NAME@.desktop</desktop-entry>
  <services>
    <service id="@SCOPE_INSTALL_NAME@">
      <description>Watch your favorite Weibo messages</description>
    </service>
  </services>
</application>


这个是微博Scope的描述文件。它定义了Scope的service id及描述

weibo.service.in


<?xml version="1.0" encoding="UTF-8"?>
<service>
  <type>sharing</type>
  <name>Weibo scope</name>
  <icon>weibo/icon.png</icon>
  <provider>@SCOPE_ACCOUNTS_NAME@</provider>
  <translations>unity-scope-weibo</translations>
</service>

这个service文件描述了微博Scope的service信息。

weibo.provider.in

这是一个微博的account provider信息。这是一个重要的文件。如果我们不能正确地设置这个文件,可能我们不能正确地访问微博account。

<?xml version="1.0" encoding="UTF-8"?>
<provider>
  <name>Weibo</name>
  <icon>weibo/icon.png</icon>
  <translations>unity-scope-weibo</translations>
  <plugin>generic-oauth</plugin>
  <domains>.*weibo\.com</domains>
  <single-account>true</single-account>

  <template>
    <group name="auth">
      <setting name="method">oauth2</setting>
      <setting name="mechanism">web_server</setting>
      <group name="oauth2">
        <group name="web_server">
          <setting name="Host">api.weibo.com</setting>
          <setting name="AuthPath">oauth2/authorize</setting>
          <setting name="TokenPath">oauth2/access_token</setting>
          <setting name="RedirectUri">https://api.weibo.com/oauth2/default.html</setting>
          <setting name="ResponseType">code</setting>
          <setting name="ClientId">your developer key</setting>
          <setting type="as" name="AllowedSchemes">['https','http']</setting>
          <setting name="ClientSecret">your developer secret</setting>
          <setting name="ForceClientAuthViaRequestBody" type="b">true</setting>  
      </group>
      </group>
    </group>
  </template>
</provider>

我们需要在“微博开放平台”去申请开发者key及secret。同时,我们一定要记得在微博的设置中做如下的设置,否则我们不能得到正确的数据。



“click”目录下的CMakeLists.txt文件内容如下:

function(configure_scope_files)
  foreach(_file ${ARGV})
    configure_file(
      "${_file}.in"
      "${CMAKE_CURRENT_BINARY_DIR}/${_file}"
      @ONLY
    )
  endforeach()
endfunction()

configure_scope_files(
  manifest.json
  weibo.provider
  weibo.service
  weibo.application
)

add_custom_target(hidden_files1
  ALL
  SOURCES
    apparmor.json
)

install(
  FILES
    "${CMAKE_CURRENT_BINARY_DIR}/manifest.json"
    "apparmor.json"
    "${CMAKE_CURRENT_BINARY_DIR}/weibo.provider"
    "${CMAKE_CURRENT_BINARY_DIR}/weibo.service"
    "${CMAKE_CURRENT_BINARY_DIR}/weibo.application"
  DESTINATION ${CMAKE_INSTALL_PREFIX}
)

install(
  DIRECTORY
    "qml-plugin"
  DESTINATION ${CMAKE_INSTALL_PREFIX}
)

这里它对该目录下的文件进行了安装。

为了能够对Scope的设置文件“weibo.ubuntu_weibo.ini.in”进行本地化的支持,我们对“data\CMakeListx.txt”加入如下的句子:

intltool_merge_translations(
  "${CMAKE_CURRENT_SOURCE_DIR}/${SCOPE_NAME}.ini.in"
  "${CMAKE_CURRENT_BINARY_DIR}/${SCOPE_INSTALL_NAME}.ini"
  ALL
  UTF8
)

这样它可以提取里面相应的英文,并在“po”目录中的.pot文件中进行翻译。

经过我们这样的修改后,我们的最基本的具有online account的设置文件已经基本已经做好了。我们可以在我们的手机或模拟器中运行我们的Scope了。在运行时,



我们选择“yes”继续运行。我们可以看到如下的画面:




者和我们所创建的最基本的Scope没有任何的差别,我们可以在手机的如下地址查看该目录的内容:



这个是我们所创建weibo provider的地方。


3)对代码进行修改

我们在上面已经对online account的配置文件做了修改。下面我们来对我们的cpp代码进行修改,为了能够使得我们使用online account,我们在query.cpp文件中加入如下的代码:

const static string SEARCH_CATEGORY_LOGIN_NAG = R"(
{
        "schema-version": 1,
        "template": {
        "category-layout": "grid",
        "card-size": "large",
        "card-background": "color:///#1ab7ea"
        },
        "components": {
        "title": "title",
        "background": "background",
        "art" : {
        "aspect-ratio": 100.0
        }
        }
        }
        )";


void Query::run(sc::SearchReplyProxy const& reply) {
    add_login_nag(reply);
 ...
}

void Query::add_login_nag(const sc::SearchReplyProxy &reply) {
    //    if (getenv("VIMEO_SCOPE_IGNORE_ACCOUNTS")) {
    //        return;
    //    }
    qDebug() << "SCOPE_INSTALL_NAME: " << SCOPE_INSTALL_NAME;
    qDebug() << "SCOPE_ACCOUNTS_NAME: " << SCOPE_ACCOUNTS_NAME;

    sc::OnlineAccountClient oa_client(SCOPE_INSTALL_NAME, "sharing", SCOPE_ACCOUNTS_NAME);

    // Check if our service is authenticated
    bool service_authenticated = false;

    int count = oa_client.get_service_statuses().size();
    qDebug() << "count: " << count;

    for ( sc::OnlineAccountClient::ServiceStatus const& status :
          oa_client.get_service_statuses())
    {
        if (status.service_authenticated)
        {
            service_authenticated = true;
            qDebug() << "Sevice is authenticated!";
            qDebug() << "account id: "  << status.account_id;
            qDebug() << "client id: " << QString::fromStdString(status.client_id);
            qDebug() << "service enabled: " << status.service_enabled;
            qDebug() << "secret: " << QString::fromStdString(status.client_secret);
            qDebug() << "access token: " << QString::fromStdString(status.access_token);
            accessToken_ = QString::fromStdString(status.access_token);

            // pass the access token to the client so that http request can be made
            client_.setAccessToken(accessToken_);
            break;
        }
    }

    if (!service_authenticated)
    {
        qDebug() << "Service is not authenicated!";

        sc::CategoryRenderer rdr(SEARCH_CATEGORY_LOGIN_NAG);
        auto cat = reply->register_category("weibo_login_nag", "", "", rdr);

        sc::CategorisedResult res(cat);
        res.set_title(_("Log-in to Weibo"));

        oa_client.register_account_login_item(res,
                                              query(),
                                              sc::OnlineAccountClient::InvalidateResults,
                                              sc::OnlineAccountClient::DoNothing);

        reply->push(res);
    }
}

重新运行我们的Scope,我们可以在手机上看到如下的画面:


我们点击“Log-in to Weibo”按钮:



我们使用我们自己的微博的账号进行登陆,在代码中,我们可以看到:



我们打开手机中的“系统设置”,再打开“账号”,当我们完成我们自己的账号登陆微博后,可以看到:



这说明我们的online account设置等已经是成功的。我们更进一步对我们的client代码进行修改,我们可以看到如下的画面:




整个项目的source code可以在如下的地址下载:

git clone https://gitcafe.com/ubuntu/weibo.git

在使用代码时,一定要在“click/weibo.provider.in”中填入自己的开发者key及secret。

更多关于online account API的例子:


作者:UbuntuTouch 发表于2015/2/3 11:51:37 原文链接
阅读:1403 评论:7 查看评论

Read more
UbuntuTouch

[原]Ubuntu OS上的QML应用框架

在我们编写QML应用的时候,我们有时事先需要来考虑我们怎么使用一个好的框架来完成我们的应用。我们的应用有多少个页面,页面之间的导航到底是怎么样子的。这个对于我们一开始来设计我们的应用来说非常中要。在这篇文章中,我们来介绍如何在上层来设计我们的应用框架。


1)使用tab来创建一个平面的导航应用


我们可以使用我们的Ubuntu SDK来创建一个最基本的叫做TabApp的应用:

   

 

这样我们就生成了我们的一个最基本的应用。我们把应用的宽度和高度设为如下的值:

    width: units.gu(50)
    height: units.gu(75)

同时,我们也修改我们的Main.qml如下:

import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Components.ListItems 1.0 as ListItem

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "tabapp.ubuntu"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(50)
    height: units.gu(75)


    Tabs {
        id: tabs

        Tab1 {
            objectName: "Tab1"
        }

        Tab2 {
            objectName: "Tab2"
        }
    }
}

在这里我们定义了两个Tab页面,分别为Tab1及Tab2。它们的内容分别为:

import QtQuick 2.0
import Ubuntu.Components 1.1

Tab {
    title: i18n.tr("Tab 1")

    Action {
        id: reloadAction
        text: "Reload"
        iconName: "reload"
        onTriggered: {
            console.log("reload is clicked")
        }
    }

    page: Page {
        Label {
            anchors.centerIn: parent
            text: i18n.tr("This is page one")
        }

        tools: ToolbarItems {
            ToolbarButton {
                action: reloadAction
            }
        }
    }
}

import QtQuick 2.0
import Ubuntu.Components 1.1

Tab {
    title: i18n.tr("Tab 2")

    page: Page {
        Label {
            anchors.centerIn: parent
            text: i18n.tr("This is page two")
        }
    }
}

这是一个最简单的Tab导航应用。我们在手机上运行:

    


所有的源码可以在地址下载:

git clone https://gitcafe.com/ubuntu/TabApp1.git


我们也可以把我们的Main.qml修改如下:

import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Components.ListItems 1.0 as ListItem

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "tabapp.ubuntu"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(50)
    height: units.gu(75)

    Action {
        id: reloadAction
        text: "Reload"
        iconName: "reload"
        onTriggered: {
            console.log("reload is clicked")
        }
    }

    Tabs {
        id: tabs
        Tab {
            title: i18n.tr("Simple page")
            page: Page {
                Label {
                    id: label
                    anchors.centerIn: parent
                    text: "A centered label"
                }
                tools: ToolbarItems {
                    ToolbarButton {
                        action: reloadAction
                    }
                }
            }
        }

        Tab {
            id: externalTab
            title: i18n.tr("External")

            page: Loader {
                id: loader
                anchors.fill: parent
                source: (tabs.selectedTab === externalTab) ? Qt.resolvedUrl("ExternalPage.qml") : ""

                onLoaded: {
                    console.log( loader.source + " is loaded")
                }
            }
        }

        Tab {
            title: i18n.tr("List view")
            page: Page {
                ListView {
                    clip: true
                    anchors.fill: parent
                    model: 20
                    delegate: ListItem.Standard {
                        iconName: "compose"
                        text: "Item "+modelData
                    }
                }
            }
        }
    }
}

运行我们的应用:


   

所有的源码在:

https://gitcafe.com/ubuntu/TabApp4.git

我们如果想在Tab架构中使用pagestack的话,我们对我们的应用必须做一些修改。我们只能把Tabs作为第一个页面推到PageStack的栈中。Main.qml具体实现如下:

import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Components.ListItems 1.0 as ListItem

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "tabapp.ubuntu"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(50)
    height: units.gu(75)

    Action {
        id: reloadAction
        text: "Reload"
        iconName: "reload"
        onTriggered: {
            console.log("reload is clicked")
        }
    }

    PageStack {
        id: pageStack
        Component.onCompleted: push(tabs)

        Tabs {
            id: tabs
            Tab {
                title: "Tab 1"
                page: Page {
                    Button {
                        anchors.centerIn: parent
                        onClicked: pageStack.push(page3)
                        text: "Press"
                    }
                }
            }
            Tab {
                title: "Tab 2"
                page: Page {
                    Label {
                        anchors.centerIn: parent
                        text: "Use header to navigate between tabs"
                    }
                }
            }
        }
        Page {
            id: page3
            visible: false
            title: "Page on stack"
            Label {
                anchors.centerIn: parent
                text: "Press back to return to the tabs"
            }
        }
    }
}


运行我们的应用,我们可以看到:

   

我们可以看见在上面显示的那样,有一个叫做“Page on stack”。可以通过按下换回箭头回到上一个页面。

具体的代码:

git clone https://gitcafe.com/ubuntu/TabApp3.git

2)使用PageStack来导航



在这一节中,我们将介绍如何使用PageStack来管理我们的页面。当用户进入下一个页面完成自己的工作后,可以通过按下标题栏中的返回箭头回到上一个页面。按照上面同样的步骤,我们可以创建一个叫做PageStack的项目。Main.qml的设计如下:

import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Components.ListItems 1.0 as ListItem

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "pagestack.ubuntu"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(50)
    height: units.gu(75)

    PageStack {
        id: pageStack
        Component.onCompleted: {
            push(page0)
        }

        Page {
            id: page0
            title: i18n.tr("Root page")
            visible: false

            Column {
                anchors.fill: parent

                ListItem.Standard {
                    text: i18n.tr("Page one")
                    onClicked: pageStack.push(page1, {color: UbuntuColors.orange})
                    progression: true
                }
                ListItem.Standard {
                    text: i18n.tr("Page two")
                    onClicked: pageStack.push(Qt.resolvedUrl("Page2.qml"))
                    progression: true
                }
            }
        }

        Page {
            title: "Rectangle"
            id: page1
            visible: false
            property alias color: rectangle.color
            Rectangle {
                id: rectangle
                anchors {
                    fill: parent
                    margins: units.gu(5)
                }
            }
        }
    }
}


这里我们在应用启动时创建一个PageStack,并同时把“page0”压入栈中。使它成为第一个页面。在“page0”中,我们有有两个列表项,分别可以进入到下一个页面中。

运行我们的应用:

   

我们可以在每个页面看见有个返回的箭头。

整个项目的源码在:

git clone https://gitcafe.com/ubuntu/PageStack.git




作者:UbuntuTouch 发表于2015/3/25 10:20:09 原文链接
阅读:810 评论:2 查看评论

Read more
UbuntuTouch

在这个视频里,介绍如何在开发Ubuntu平台上开发Webapps及HTML 5的应用。


http://v.youku.com/v_show/id_XODkwNDQxMDQ0.html

作者:UbuntuTouch 发表于2015/2/10 19:26:33 原文链接
阅读:817 评论:0 查看评论

Read more
UbuntuTouch

我们可以看到在Ubuntu SDK中有一个自己的WebView。它没有采用Qt标准的Webkit库。在Ubuntu上,我们对下面的引擎做了很多的优化(oxide引擎),这样使得我们的WebView性能更加优越。


下面我们通过一个例子来设计出一个简单的Browser。


import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Web 0.2
import QtQuick.Layouts 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "browser.liu-xiao-guo"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
    useDeprecatedToolbar: false

    width: units.gu(100)
    height: units.gu(75)

    Page {
        title: i18n.tr("")

        RowLayout {
            id:toolbar
            anchors.top: parent.top
            width: parent.width
            height: units.gu(8)
            spacing: units.gu(1)

            Icon {
                id: back
                anchors.verticalCenter: parent.verticalCenter
                name: "go-previous"
                height: input.height
                width: height
                visible: webview.canGoBack

                MouseArea {
                    anchors.fill: parent
                    onClicked: webview.goBack();
                }
            }
            Icon {
                id: forward
                anchors.verticalCenter: parent.verticalCenter
                name: "go-next"
                height: input.height
                width: height
                visible: webview.canGoForward
                MouseArea {
                    anchors.fill: parent
                    onClicked: webview.goForward();
                }
            }

            TextField {
                id: input
                anchors.verticalCenter: parent.verticalCenter
                height: parent.height - units.gu(1)
                Layout.maximumWidth: parent.width
                Layout.preferredWidth: parent.width - back.width - forward.width
                text: "http://www.baidu.com"

                onAccepted: {
                    webview.url = input.text
                }
            }
        }

        WebView {
            id: webview
            anchors.top: toolbar.bottom
            height: parent.height - toolbar.height
            width: parent.width

            url: "http://www.baidu.com"
        }

    }
}


在这里,我们使用了:

import Ubuntu.Web 0.2

模块。在上面我们使用了两个Icon来返回或向前看。同时我们设计了一个TextField来输入我们想要去的地址。注意地址必须是以http开始的字符串。当我们按下enter键后,就会自己打开页面。


  


  


代码不多,但是它完成了我们想要完成的东西。

整个项目的源码在:git clone https://gitcafe.com/ubuntu/browser.git



作者:UbuntuTouch 发表于2015/6/8 14:14:41 原文链接
阅读:542 评论:0 查看评论

Read more