QtQuick桌面应用开发指导 1)关于教程 2)原型和设计 3)实现UI和功能_A

Release1.0 http://qt-project.org/wiki/developer-guides

Qt Quick Application Developer Guide for Desktop

这个教程的目的是让你熟悉使用QtQuick构建QML程序的最佳编程实践方法; 先决条件: 对QML有相当的理解, 相关阅读: <qtquick/qtquick-applicationdevelopers.html>; 本教程会涉及QML开发最佳实践的各个方面, 以及在典型的桌面环境下部署应用的情况; 参阅更多相关的信息源可以让你对QML编程的理解更深刻;

CHAPTER1 关于教程

1.1 为何阅读

这份教程对于开发丰富特性的应用以及在多种桌面平台部署应用的情况, 提供了一个QML和QtQuick技术总览;

重点在于QtQuick和如何有效地编写整个应用而不使用C++; 教程一步步指导你如何初始化开发环境, 配置一个可以部署的新项目; 这里有一个简单应用(NoteApp);

这里有许多章节, 每一步都会特定描述应用的特性, 开发方式和QML代码细节; 应用覆盖了各个方面, 例如高级UI概念, 包括animation, database storage和Javascript应用程序逻辑;

这个应用看起来不会像典型或经典的桌面程序, 普通的UI元素比如 toolbar, menu, dialog之类没有被使用; 这个应用是受到现代的流UI(fluid UIs)启发, 目标是桌面环境;

为了方便描述, NoteApp* 对应每个章节有自己的版本; 建议阅读教程的时候参考代码;

教程结束时, 你应该有对使用QML语言, 利用QML/QtQuick技术开发程序有一个深入理解;

NoteApp*程序的截图;

1.2 源代码

1.3 License

---1End---

CHAPTER2 设计原型和起始设计

QtQuick和QML的一大优点是, 它使得你可以快速开发原型; 考虑Prototyping阶段作为开发NoteApp程序的第一步有两个原因: 1) 前面提到过, QML让我们可以快速开发原型, UI设计师可以不费劲地草绘出一些初始化一些UI屏幕; 2) 原型可以让你和设计者紧密合作, UI概念的应用将在几个很短的迭代过程中完成;

接下去, 这个原型将作为继续开发的基础; 这章中, 我们将引导你实施开发阶段, 包括UI概念, 特性集合, UI交互流程, 一些初始化的QML屏幕作为原型的一部分; 其中会有一些主要QML概念的介绍, 比如创建QML组件以及QML item布局;

这章主要讨论点的简要列表:

- UI概念和特性集合

- 使用QtCreator创建QML组件

- 使用Anchor和Repeater类型来给UI元素布局

2.1 NoteApp程序概览

NoteApp程序是一个便利贴(Post-it note) [http://en.wikipedia.org/wiki/Post-it_note]程序, 帮助用户创建note并且在本地存储; 如果note有一个类别(category)的话, 就更易管理, 因此考虑有三种不同的类别; 根据视觉的角度来看, 一个类别可以被一个区域表示; 我们来介绍一下Page的概念; 一个Page是一个区域,
在这个区域中可以创建note并且放置进去;

用户应该可以一个一个地删除note, 也可以一次性全部删除; note可以自由地在Page区域中移动; 为了简化, 我们定义三个Page然后使用 Marker来识别每张Page; 另外, 每个marker可以有不同的颜色;

一个有趣的特性是本地存储note, 而且可能是自动完成, 不用询问用户是否存储;

总结下特性:

- 创建/删除 Note item;

- 编辑Note和在page中任意位置放置note

- 本地存储note

- 三个不同page由一个page marker表示

2.1.1 UI元素

基于前面讨论的需求, 我们从一个线框(wire-frame)设计开始; 由于NoteApp可能有很多种的设计, 让我们考虑采用其中一种;

从UI的角度看, 上面的图片给出了用户想要的样子, 而且它也能帮助你找到可能的UI元素, 以及可以应用的交互;

2.1.2 UI流程(Flows)

如前面所提到的, 有三个Page可以包含Note item; 我们也可以在右边看到Marker, 左边看到toolbar; toolbar包含: New Note工具--创建新的note; Clear All工具--清除整个page; Note item有一个toolbar可以用来拖拽(drag)note, 按下鼠标左键, 移动鼠标可以在page中拖动note; 另外, note toolbar上还有一个 delete工具可以删除note;

下一步

?要确认特性中需要实现的QML组件, 以及如何创建它们;

2.2 为UI元素创建一个QML组件

一旦我们恰当地定义了特性集合和UI概念, 确认了基本的UI元素, 就可以安全地开始实现NoteApp的原型;

原型可以是非常基础的UI, 没有任何功能, 但是它提供了这个程序在经过迭代实现后, 在完成时看上去的大概样子;

这一步中, 你会找到使用QtCreator创建QtQuick UI的细节, 但最重要的是, 如何确定和创建一个QML组件;

2.2.1 QtCreator中创建一个QtQuick UI项目

在原型阶段, 很重要的一点是, 创建一个Qt Quick UI项目是推荐的方式, 是一个有效的方法; 这种方式下, prototyping, 特别是开发和测试每个独立的QML组件更简单; 独立地测试每个新建的组件是很重要的, 这样你才能立刻定位错误, 使用QtQuick UI项目让这一切更简单;

更多细节参考 Creating a Qt Quick UI http://qt-project.org/doc/qtcreator-2.6/quick-projects.html#creating-qt-quick-ui-projects;

Note: 总是要有一个QML文件, 定义为主文件来加载和运行程序; 对于NoteApp, 我们有main.qml, 它是由QtCreator产生的文件;

2.2.2 识别作为UI元素的QML组件

如果想要和面向对象编程做一个类比, QML组件可以看作类, 用来定义和实例化对象; 你可能会用一个大的QML文件来写一整个简单程序, 但是那样可能会增加复杂性, 使得代码重用性和维护十分困难--有些甚至是不可能;

QML组件可以被看成是一个普通UI元素的小组; 更多情况下, 它代表一个UI元素以及预定义的action和property;

基于我们的UI概念和设计, 这里有一个, 这里有一个自定义QML组件列表, 在接下去的迭代中会用到;

Note: 每个QML组件使用自己的QML文件(.qml), qml文件和组件的名字一样; 例如, Note组件会命名为 Note.qml;

- Note 代表note item;

- Page 这个组件包含item;

- Marker 代表一个page marker, 让户可以使用marker在page之间切换;

- NoteToolbar  在note item上的toolbar用来拖拽和布局

更多使用QtCreator创建组件的细节参考: Creating QML Components with QtCreator3 http://qt-project.org/doc/qtcreator-2.6/quick-components.html

下一步

接下去看如何进一步强化定义的组件以及开始实现原型UI;

2.3 Anchoring QML Item和实现QML组件

Rectangle QML类型是构建UI块的一个自然的选择, 也可作为在prototype阶段初始化QML的组件; 它是一个拥有属性的visual类型, 你可以随意调整它, 使得prototype和test更为简单;

Note: 总是使用一样的默认几何数据来定义组件是一个好习惯, 有助于测试;

让我们来看看QML组件的代码; 首先, 我们开始实现Note组件;

2.3.1 Note和 NoteToolbar组件

首先, 就像前面步骤中所见, 我们已经创建了一个新的QML文件用来实现所需的组件;

要符合线框设计, 代码看起来会是下面这样:

// NoteToolbar.qml


1

2

3

4

5

6

7

8

import
QtQuick 2.0

//
A Rectangle element with defined geometries and color.

Rectangle
{

    id:
root

    width:
100

    height:
62

    color: "#9e964a"

}

Note组件有一个toolbar UI元素 -- NoteToolBar组件; 另外, 有一个 text input元素来获取用户输入文字; 我们使用 TextEdit QML类型; 为了把这些UI元素放入Note组件, 要使用anchor属性; 这个属性继承自 Item类型--是最基本的类, 每个QML组件默认继承自它;

更多布局细节参考 Anchor-based Layout in QML http://qt-project.org/doc/qt-5/qtquick-positioning-anchors.html  ;

Note Anchor-based Layout不能和绝对位置混用;

// Note.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

import
QtQuick 2.0

Rectangle
{

    id:
root

    width:
200

    height:
200

    color: "#cabf1b"

    //
creating a NoteToolbar that will

    //
be anchored to its parent on the top, left and right

    NoteToolbar
{

        id:
toolbar

        //
height is required to be specified

        //
since there is no bottom anchoring.

        height:
40

        //
anchoring it to the parent

        //
using just three anchors

        anchors
{

            top:
root.top

            left:
root.left

            right:
root.right

        }

    }

    //
creating a TextEdit used for the text input from user.

    TextEdit
{

        anchors
{

            top:
toolbar.bottom

            bottom:
root.bottom

            right:
root.right

            left:
root.left

        }

        wrapMode:
TextEdit.WrapAnywhere

    }

}

Warning 由于性能原因, anchor应该只用在兄弟(sibling)或直接的父类(parent)上;

2.3.2 Page

一旦Note组件好了, 就可以开始Page组件的工作, 放两个Note在里面;

// Page.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Rectangle
{

    id:
root

    width:
600

    height:
400

    color: "#222525"

    //
creating a Note item

    Note
{

        id:
note1

        //
use x and y properties to specify

        //
the absolute position relative to the parent

        x:
105; y: 144

    }

    Note
{

        id:
note2

        x:
344

        y:
83

    }

}

在QtCreator中, 你可以简单地运行上面的文件, 实际上使用 qmlscense加载Page.qml更简单;

2.3.3 Marker

和其余的组件一样, Marker组件也使用Rectange类型和预定义的几何形状; 后面会看到怎样使用Marker组件;

// Marker.qml


1

2

3

4

5

6

Rectangle
{

    id:
root

    width:
50

    height:
90

    color: "#0a7bfb"

}

下一步

下一章我们会看到如何使用 Repeater QML类型和 使用Column来管理一个静态的marker列表;

2.4 使用Repeater和Delegate来创建Marker的List

在前面, 我们看到了如何创建QML组件: Note, NoteToolbar, Page, Marker, 以及如何使用 anchors放置QML组件;

回顾之前的设计概念, 我们注意到三个 Marker元素是垂直并排的; 使用 anchors可以固定UI元素做到这个要求, 但是那样会增加代码复杂度; QML有方便的方式--layout和 positioning类型; Column类型是其中一个, 使得UI元素可以一个接一个排成一列;

因为我们想要放三个Marker组件在 Column中, 可以使用方便的QML类型--Repeater;

现在看下面的代码:


1

2

3

4

5

6

7

8

9

10

11

12

Column
{

    id:
layout

    //
spacing property can set to let the item have space between them

    spacing:
10

    //
a Repeater item that uses a simple model with 3 items

    Repeater
{

        model:
3

        delegate:

        //
using the Marker component as our delegate

        Marker
{ id: marker }

    }

}

上面代码中, Repeater产生三个QML组件, 基于model和delegate; 由于我们想要三个Marker item, 就简单地使用Marker组件作为 delegate;

更多关于 positioning的信息参阅 Important Concepts In Qt Quick - Positioning http://qt-project.org/doc/qt-5.0/qtquick/qtquick-positioning-topic.html

一个问题很自然地出现:"上面代码要放在哪个qml文件的哪个位置?"; 我们需要一个独立的QML组件--MarkerPanel; MarkerPanel是一个简单列表, 包含三个Marker item可以用作UI元素;

// MarkerPanel.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Rectangle
{

    id:
root

    width:
50

    height:
300

    //
column type that anchors to the entire parent

    Column
{

        id:
layout

        anchors.fill:
parent

        spacing:
10

        Repeater
{

            //
just three Marker items

            model:
3

            delegate:

                Marker
{ id: marker }

        }

    }

}

Note: 建议总是在prototype阶段对组件进行独立地运行和测试; 这样你可以立刻定位错误;

运行 MarkerPanel组件:

下一步

我们将会看到如何使用创建出来的组件来完成原型;

2.5 完成原型

现在QML组件都就绪了, 可以用来构建我们的原型;

- Note    - NoteToolbar    -Marker    -MarkerPanel    -Page

在接下去的阶段中可能会有更多QML组件出现;

前面提到过, QtCreator产生一个 main.qml可以当作main文件来加载和运行NoteApp; 因此, 我们开始在 main.qml中安排组件, 组合出一个原型;

2.5.1 组合出原型

回到UI概念, 再看一下设计, 然后开始布局; 我们有Marker的面板(panel)--MarkerPanel组件放在右边, Page组件在中间; 目前为止还没有提到 toolbar;

toolbar包含两个工具, 一个用来创建新的note, 一个是清除Page; 为了简化, 我们不为它创建一个组件了, 直接在main.qml中定义它;

代码大致这样:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

//
using a Rectangle element to represent our toolbar

//
it helps to align the column better with the rest of the components

Rectangle
{

    id:
toolbar

    //
setting a width because there is no right anchoring

    width:
50

    color: "#444a4b"

    anchors
{

        left:
window.left

        top:
window.top; bottom: window.bottom

        topMargin:
100; bottomMargin: 100

    }

    //
using a Column type to place the tools

    Column
{

        anchors
{ fill: parent; topMargin: 30 }

        spacing:
20

        //
For the purpose of this prototype we simply use

        //a
Repeater to generate two Rectangle items.

        Repeater
{

            model:
2

            //
using a Rectangle item to represent

            //
our tools, just for prototype only.

            Rectangle
{ width: 50; height: 50; color: 
"red" }

        }

    }

}

现在, 可以实现我们的原型了;

// main.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

Rectangle
{

    //
using window as the identifier for this item as

    //
it will the only window of the NoteApp

    id:
window

    width:
800

    height:
600

    //
creating a MarkerPanel item

    MarkerPanel
{

        id:
markerPanel

        width:
50

        anchors.topMargin:
20

        anchors
{

            right:
window.right

            top:
window.top

            bottom:
window.bottom

        }

    }

    //
the toolbar

    Rectangle
{

        id:
toolbar

        width:
50

        color: "#444a4b"

        anchors
{

            left:
window.left

            top:
window.top

            bottom:
window.bottom

            topMargin:
100

            bottomMargin:
100

        }

        Column
{

            anchors
{ fill: parent; topMargin: 30 }

            spacing:
20

            Repeater
{

                model:
2

                Rectangle
{

                    width:
50;

                    height:
50;

                    color: "red"

                }

            }

        }

    }

    //
creating a Page item

    Page
{

        id:
page1

        anchors
{

            top:
window.top

            bottom:
window.bottom

            right:
markerPanel.left

            left:
toolbar.right

        }

    }

}

运行起来是这样的:

2.5.2 让Note组件可以拖拽

目前我们有了一个基础的原型, 可以作为NoteApp UI的架子; 有一个酷炫的UI功能在原型阶段就可以完成--让用户在page里拖拽note item; 要做到这点, MouseArea QML Type有个属性群叫做drag; 我们将使用 drag.target 属性, 将note组件的 id设置给它;

考虑到用户会使用 NoteToolbar来拖拽一个note, MouseArea类型应该放在 NoteToolbar组件里面; NoteToolbar会处理用户的拖拽操作, 我们应该把 drag.target设置成Note组件;

想做到这点, 我们要允许NoteToolbar在Note之中将 MouseArea的drag.target属性绑定到Note的id; QML提供了 Property Aliases http://qt-project.org/doc/qt-5/qtqml-syntax-objectattributes.html#property-aliases 
来实现这一点;

我们来为NoteToolbar中MouseArea的drap属性组创建一个property alias(属性别名);

// NoteToolbar.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

Rectangle
{

    id:
root

    width:
100

    height:
62

    color: "#9e964a"

    //
declaring a property alias to the drag

    //
property of MouseArea type

    property
alias drag: mousearea.drag

    //
creating a MouseArea item

    MouseArea
{

        id:
mousearea

        anchors.fill:
parent

    }

}

从上面的code可见, NoteToolbar的drag属性别名绑定到了MouseArea的drag属性, 现在就可以在Note组件中使用它了;

// Note.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

Rectangle
{

    id:
root

    width:
200

    height:
200

    color: "#cabf1b"

    //
creating a NoteToolbar that will be anchored to its parent

    NoteToolbar
{

        id:
toolbar

        height:
40

        anchors
{

            top:
root.top

            left:
root.left

            right:
root.right

        }

        //
using the drag property alias to

        //
set the drag.target to our Note item.

        drag.target:
root

    }

    //
creating a TextEdit

    TextEdit
{

        anchors
{

            top:
toolbar.bottom

            bottom:
root.bottom

            right:
root.right

            left:
root.left

        }

        wrapMode:
TextEdit.WrapAnywhere

    }

}

更多细节参考 Property Binding http://qt-project.org/doc/qt-5/qtqml-syntax-propertybinding.html

下一步

基于原型开始实现UI和基本功能;

---2End---

CHAPTER3 实现UI和添加功能

初始的原型引入的是基础的UI和NoteApp功能概念, 可以帮助我们找出所需的QML组件;

基于原型, 我们朝着更完整的UI和功能, 试着构建一个可以工作的程序; 现在, 使用目前实现的组件开始组合出这个程序的UI;

这一章更多关于QML图形, 图像, 背景, 强化UI, 同时也使用Javascript添加方法; 你可以看到一些QML类型更深层的内容, 通过一点点增加代码复杂度, 添加功能来了解更多;

要点:

- 引入PagePanel组件, 使用Repeater元素管理Page元素;

- 使用QML图形;

- 更深入使用QML类型;

3.1 创建PagePanel组件

方便起见, 我们用Page组件只创建一个page item; 我们已经把它放置到其他item一起, anchor到它的parent; 无论如何, NoteApp概念和需求是要求三个不同page, 然后用户可以使用marker导航(navigate)到任何一个; 我们可以看到MarkerPanel组件如何帮助我们创建和布局三个Marker item, 接下去可以使用相同方法处理Page item, 这样实现PagePanel组件;

3.1.1 使用一个Item类型

在我们更进一步之前, 理解为什么Rectangle类型在组件中作为顶层这样的设计, 现在开始要防止出现; 原因是我们使用Rectangle元素是因为它可以帮助我们迅速得到可视化的结果, 这也是原型阶段的需求;

但一旦原型完成, 用 Item类型替换 Rectangle类型会更合理, 特别当考虑到拿图形作为背景的UI元素;

// Page.qml


1

2

Item
{

    id:
root

Warning: 从现在开始, 考虑用 Item QML类型来作为组件的顶层元素; 参考每一章的源代码;

3.1.2 使用States

继续PagePanel组件的开发, 可见PagePanel和MarkerPanel之间主要的区别是三个Marker item应该总是可见的, 但是Page item同时只能有一个是可见的; 这依赖于用户点选了哪个Marker item;

实现这个行为可以有多种方式; 其中一个是inline(内联) Javascript方法, 根据当前用户点选的Marker切换(toggle) Page item的可见性;

在NoteApp里面, 我们使用了 State类型实现所需要的行为; PagePanel组件有三个state, 每个都绑定到一张Page的 visible属性; 因此在page之间切换的事件时候就转换成了在PagePanel里面设置独立的状态;

首先, 在Page组件里, 我们要设置 opacity(透明度)属性为0.0作为默认值; 这是为了让page在初始的时候不可见, 然后基于各自的state改变让它们变得可见;

// Page.qml


1

2

3

4

5

Item
{

    id:
root

    opacity:
0.0

...

}

一旦创建了PagePanel.qml文件, 就可以开始创建state和Page item; 我们需要三个state:

- personal fun work

这会改变下面每个Page对应各自的opacity属性: personalpage     funpage    workpage

下面的图示展示了state关联到各自的page;

// PagePanel.qml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

Item
{

    id:
root

    //
creating the list of states

    states:
[

        //
creating a state item with its corresponding name

        State
{

            name: "personal"

            //the
properties that are about to change for a defined target

            PropertyChanges
{

                target:
personalpage

                opacity:1.0

                restoreEntryValues: true

            }

        },

        State
{

            name: "fun"

            PropertyChanges
{

                target:
funpage

                opacity:1.0

                restoreEntryValues: true

            }

        },

        State
{

            name: "work"

            PropertyChanges
{

                target:
workpage

                opacity:1.0

                restoreEntryValues: true

            }

        }

    ]

    //
creating three page items that are anchored to fill the parent

    Page
{ id: personalpage; anchors.fill: parent }

    Page
{ id: funpage; anchors.fill: parent }

    Page
{ id: workpage; anchors.fill: parent }

}

Note: 设置 restoreEntryValues 属性为true可以让target变化后的属性重设成默认值, 这样当state变化的时候, page的opacity属性可以被重设为false;

观察上面的代码, 可以看到三个Page item创建出来了, 不同的state会改变这些item的opacity属性; 这一步, 我们设法创建了一个新的组件--PagePanel, 可以帮助我们使用三个state切换页面;

下一步

使用Marker item变换PagePanel item的state;

---TBC---

时间: 2024-11-03 21:44:33

QtQuick桌面应用开发指导 1)关于教程 2)原型和设计 3)实现UI和功能_A的相关文章

QtQuick桌面应用开发指导 7)创建应用 8)扩展

CHAPTER7 部署NotApp应用 现在我们要让程序在典型的桌面环境中可用, 可部署; 如第一章所描述, 我们在QtCreator中使用QtQuick UI项目开发NoteApp程序; 这意味着qmlscene用来加载main.qml, 随之让NoteApp运行; 首先, 让NoteApp可用的最简单方案是创建一个package(包)将所有qml文件, qmlscense和一个可以运行qmlscense加载main.qml的简单脚本bundle(捆扎)起来; 你需要参考每一个桌面平台, 了解

QtQuick桌面应用开发指导 4)动态管理Note对象_B 5)外观加强 6)更多改进

4.2.2 Stateless(状态无关的)JavaScript库 为了让开发轻松点, 使用一个JavaScript接口来和数据库交互是个好主意, 它在QML中提供了方便的方法; 在QtCreator中创建一个新的JavaScript文件 noteDB.js, 保证选择了 State Library选项; 这样使得noteDB.js用起来像一个库, 提供了stateless的helper方法; 这样,在每个QML组件 import noteDB.js以及使用它的时候, 就只有一份实例被加载和使用

QtQuick桌面应用开发指导 3)实现UI和功能_B 4)动态管理Note对象_A

3.2 把Page Item和Marker Item绑定 之前我们实现了PagePanel组件, 使用了三个state来切换Page组件的opacity属性; 这一步我们会使用Marker和MarkerPanel组件来实现页面导航; 在原型阶段, MarkerPanel组件十分简单, 没有任何功能; 它使用了Repeater类型来产生三个QML Item以及Marker组件作为delegate; MarkerPanel应该存储当前激活的marker(标记), 即那个被用户点击的marker; 基

nw.js桌面软件开发系列 第0.1节 HTML5和桌面软件开发的碰撞

第0.1节 HTML5和桌面软件开发的碰撞 当我们谈论桌面软件开发技术的时候,你会想到什么?如果不对技术本身进行更为深入的探讨,在我的世界里,有这么多技术概念可以被罗列出来(请原谅我本质上是一个Windows程序员的事实). 操作系统 API.操作系统发展到今日,几乎桌面应用的所有功能,都是基于系统API构建的.调用API和语言及技术无关,哪怕是使用汇编.例如(代码来源于网络,本地重新编译): ;我的第一个win32汇编程序 ;一个经典的hello world !程序 ;>>>>&

转桌面端开发的感受

最近由Java服务端开发转到了桌面端开发,之前的项目暂时不需要更新维护,保持原样. 不仅仅是我转向了桌面端开发(主要针对VsCode二次开发),连安卓方面的那两个人也是如此. 之前我和另外JAVA的两个小伙伴是公司的前后台开发,而我就多兼任一个运维,至于测试,人人都是测试,彼此互测对方开发的软件. 转向桌面端开发(主要对VsCode二次开发),目前仅仅也只是看懂部分相关的javascript.css及其typescript的. 从来没有接触过桌面端开发.前端.运维.后台.自动化测试我都没怕过,这

C++开发人脸性别识别教程(13)——针对单张图片的性别识别

在之前的博文中我们的性别识别程序已经初步成型,能够识别某个文件夹下的图片文件.不过这里有一个问题,假设这个文件夹下有着大量的图片,而我们希望识别这些图片中的某一张,此时需要我们不停的单击“下一张”按钮才会轮询到对应的图片,这是相当麻烦的,因此在这篇博客中我们向程序中添加一个功能——单张图片的性别识别. 一.基本思想 最基本的办法就是在主界面再添加一个按钮控件,命名为“图片文件”(之前的按钮为“图片文件夹”),不过这样会使得界面上的按钮控件过于繁多,给人一种“作者只会用button控件”的感觉.这

Jetty开发指导:Maven和Jetty

使用Maven Apache Maven是一种软件项目管理和综合工具.基于项目对象模型(POM)的概念,Maven能从核心信息管理一个项目的构建.报告和文档. 他是用于构建一个web应用项目的理想工具,这些项目能用jetty-maven-plugin轻松的运行web应用,从而节省开发时间.你也能用Maven构建.测试和运行一个嵌入Jetty的项目. 首先我们将看一个很简单嵌入Jetty的HelloWorld Java应用,然后看一个简单的webapp怎么使用jetty-maven-plugin加

PHP开发工具PHP基础教程

    PHP开发 工具PHP基础教程,以下是兄弟连PHP培训小编整理: PHP IDE PHP IDE也不少,主要从几个方面进行筛选: 跨平台(能够同时在windows,mac或者ubuntu上面运行) 版本控制(SVN,GIT) 文件历史(自动记录历史改动) 多语言支持(至少支持html+css+javascript的智能提示和代码补全,支持Zencode),当然现在的IDE基本都可以通过安装扩展来实现 方便的TODO LIST,系统命令行 远程文件同步 方便调试 界面好看...... 好了

使用IntelliJ IDEA 13搭建Android集成开发环境(图文教程)

原文:使用IntelliJ IDEA 13搭建Android集成开发环境(图文教程) ?[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4013535.html 联系方式:[email protected] [正文] [开发环境] 物理机版本:Win 7旗舰版(32位) Java SDK版本:jdk1.8.0_20(32位) Android SDK