自 QML 第一次发布已经过去一年多的时间,但在企业应用领域,QML 一直没有能够占据一定地位。很大一部分原因是,QML 缺少一些在企业应用中亟需的组件,比如按钮、菜单等。虽然移动领域,这些组件已经变得可有可无,但在桌面系统中依然不可或缺。为了解决这一问题,Qt 5.1 发布了 Qt Quick 的一个全新模块:Qt Quick Controls。顾名思义,这个模块提供了大量类似 Qt Widgets 模块那样可重用的组件。本章我们将介绍 Qt Quick Controls,你会发现这个模块与 Qt 组件非常类似。
为了开发基于 Qt Quick Controls 的程序,我们需要创建一个 Qt Quick Application 类型的应用程序,选择组件集的时候注意选择 Qt Quick Controls 即可:
注意,Qt Creator 给出的是 Qt Quick Controls 1.0,而最新版本的 Qt 5.2 搭载的 Qt Quick Controls 是 1.1。1.1 比 1.0 新增加了一些组件,比如BusyIndicator
等。所以,如果你发现某个组件找不到,记得更新下 Qt Quick Controls 的版本。
Qt Quick Controls 1.1 提供了多种组件:
应用程序窗口 | |
用于描述应用程序的基本窗口属性的组件 | |
ApplicationWindow | 对应QMainWindow ,提供顶层应用程序窗口 |
MenuBar | 对应QMenuBar ,提供窗口顶部横向的菜单栏 |
StatusBar | 对应QStatusBar ,提供状态栏 |
ToolBar | 对应QToolBar ,提供工具栏,可以添加ToolButton 和其它组件 |
Action | 对应QAction ,提供能够绑定到导航和视图的抽象的用户界面动作 |
导航和视图 | |
方便用户在一个布局中管理和显示其它组件 | |
ScrollView | 对应QScrollView ,提供滚动视图 |
SplitView | 对应QSplitter ,提供可拖动的分割视图布局 |
StackView | 对应QStackedWidget ,提供基于栈的层叠布局 |
TabView | 对应QTabWidget ,提供带有标签的基于栈的层叠布局 |
TableView | 对应QTableWidget ,提供带有滚动条、样式和表头的表格 |
控件 | |
控件用于表现或接受用户输入 | |
BusyIndicator | 提供忙等示意组件 |
Button | 对应QPushButton ,提供按钮组件 |
CheckBox | 对应QCheckBox ,提供复选框 |
ComboBox | 对应QComboBox ,提供下拉框 |
GroupBox | 对应QGroupBox ,提供带有标题、边框的容器 |
Label | 对应QLabel ,提供标签组件 |
ProgressBar | 对应QProgressBar ,提供进度条组件 |
RadioButton | 对应QRadioButton ,提供单选按钮 |
Slider | 对应QSlider ,提供滑动组件 |
SpinBox | 对应QSpinBox ,提供微调组件 |
Switch | 提供类似单选按钮的开关组件 |
TextArea | 对应QTextEdit ,提供能够显示多行文本的富文本编辑框 |
TextField | 对应QTextLine ,提供显示单行文本的纯文本编辑框 |
ToolButton | 对应QToolButton ,提供在工具栏上显示的工具按钮 |
ExclusiveGroup | 提供互斥 |
菜单 | |
用于构建菜单的组件 | |
Menu | 对应QMenu ,提供菜单、子菜单、弹出菜单等 |
MenuSeparator | 提供菜单分隔符 |
MenuItem | 提供添加到菜单栏或菜单的菜单项 |
StatusBar | 对应QStatusBar ,提供状态栏 |
ToolBar | 对应QToolBar ,提供工具栏,可以添加ToolButton 和其它组件 |
我们尝试实现一个编辑器。这是一个简单的文本编辑器,具有新建、剪切、复制和粘贴等操作。程序运行出来效果如下:
整个程序都是在 IDE 帮我们生成的 main.qml 中实现的。首先我们需要添加import
语句:
import QtQuick 2.1 import QtQuick.Controls 1.1
注意我们修改了 IDE 生成的默认语句。整个 QML 文档的根元素是ApplicationWindow
:
ApplicationWindow { title: qsTr("Simple Editor") width: 640 height: 480 ... }
ApplicationWindow
是应用程序的主窗口,类似QMainWindow
,提供了很多预定义的功能,比如菜单、工具栏等。代码里面的qsTr()
函数类似tr()
函数,用于以后的国际化。所有面向用户的文本都应该使用这个函数。
下面向ApplicationWindow
中添加控件:
menuBar: MenuBar { Menu { title: qsTr("&File") MenuItem { action: newAction } MenuItem { action: exitAction } } Menu { title: qsTr("&Edit") MenuItem { action: cutAction } MenuItem { action: copyAction } MenuItem { action: pasteAction } MenuSeparator {} MenuItem { action: selectAllAction } } } toolBar: ToolBar { Row { anchors.fill: parent ToolButton { action: newAction } ToolButton { action: cutAction } ToolButton { action: copyAction } ToolButton { action: pasteAction } } } TextArea { id: textArea anchors.fill: parent }
首先看最后面的TextArea
,这是整个窗口的主要控件,类似于setCentralWidget()
函数调用。
menuBar
和toolBar
两个属性都是ApplicationWindow
提供的属性。
menuBar
是MenuBar
类型的,所以我们创建一个新的MenuBar
控件。MenuBar
具有层次结构,这是通过Menu
的嵌套实现的。每一个菜单项都是用MenuItem
实现的;菜单项之间的分隔符则使用MenuSeparator
控件。这点与 QtWidgets 有所不同。
toolBar
是Item
类型的,不过通常都会使用ToolBar
控件。ToolBar
默认没有提供布局,因此我们必须给它设置一个布局。这里我们直接添加了一个Row
,作为横向工具栏的布局。这个工具栏要横向充满父窗口,因此设置锚点为anchors.fill: parent
。虽然我们设置的是充满整个父窗口,但是工具栏的行为是,如果其中只有一个子元素(比如这里的Row
),那么工具栏的高度将被设置为这个子元素的implicitHeight
属性。这对结合布局使用非常有用。事实上,这也是工具栏最常用的方法。工具栏中添加了四个按钮,都是ToolButton
类型。
每一个MenuItem
和ToolButton
都添加了一个action
属性。下面是这部分代码:
Action { id: exitAction text: qsTr("E&xit") onTriggered: Qt.quit() } Action { id: newAction text: qsTr("New") iconSource: "images/new.png" onTriggered: { textArea.text = ""; } } Action { id: cutAction text: qsTr("Cut") iconSource: "images/cut.png" onTriggered: textArea.cut() } Action { id: copyAction text: qsTr("Copy") iconSource: "images/copy.png" onTriggered: textArea.copy() } Action { id: pasteAction text: qsTr("Paste") iconSource: "images/paste.png" onTriggered: textArea.paste() } Action { id: selectAllAction text: qsTr("Select All") onTriggered: textArea.selectAll() }
Action
类似QAction
。这里我们还是使用qsTr()
函数设置其显示的文本。
使用iconSource
属性可以指定图标。注意这里的图标只能是位于文件系统中的,不能加载资源文件中的图标(当然,这并不是绝对的。如果我们将整个 QML 文档放在资源文件中,那么就可以直接加载资源文件中的图标。我们会在后面的章节详细介绍这种技术。)。当我们直接类似“images/new.png”这种路径时,注意 QML 是运行时解释的,因此这个路径是相对与 QML 文件的路径。所以这里的图标需要放在与 main.qml 文件同目录下的 images 目录中。
onTriggered
属性是一种信号处理函数,后面可以添加 JavaScript 语句。如果是多条语句,可以使用大括号,例如newAction
的onTriggered
。QML 组件可以发出信号。与 C++ 不同的是,QML 组件的信号并不需要特别的连接语句,而是使用"on信号名字"的形式。比如,Action
有一个名为triggered
的信号,则其信号处理函数即为onTriggered
。事实上,这是最简单的一种信号槽的实现。不过,这种实现的困难在于,同一个信号只能有一个固定名字的信号处理函数。不过,我们也可以使用 connect 连接语句。后面的章节中将详细介绍这一点。
至此,我们的编辑器便实现了。由于全部使用了TextArea
提供的功能,所以代码很简单。不过,复杂的程序都是这些简单的元素堆积而成,所以,我们现在只是简单介绍,具体的控件使用还要根据文档仔细研究。
38 评论
想請問自己建置的QtQuick跟Qt提供的Example code的差別
QtQuick2ApplicationViewer viewer;
跟QQuickView view; 的差別是?
QtQuick2ApplicationViewer 是 IDE 帮助生成的一个类,封装了 QQuickWindow。在一定程度上,QtQuick2ApplicationViewer 可以认为是 QQuickWindow 的子类。QQuickView 是 QQuickWindow 的子类,增加了直接读取 QML 文件等功能。
謝謝解釋!
因為初學,想藉由模仿example code來學習,但發現光main.cpp長相都不一樣,害我有點不知如何下手來模仿...
非常不错,先收藏了。 感觉访问的时候有点慢。豆子大大不是建在阿里云的嘛?怎么感觉访问不怎么理想呢?
不是的,网站用的是国外的主机,没有在阿里云上面,因为考虑到这个主机还有近一年时间的续费,而且国内主机的话备案也要一段时间,所以还没有迁移。
qt 5.2.1for x86里Controls 是 1.0的。请问怎么更新呢?
Qt 5.2.1 带的就是 1.1 的,不需要更新。只需要将 IDE 生成的 import QtQuick.Controls 1.0 改成 1.1 就可以了。
楼主的书什么时候出来啊?
最新与出版社联系的结果是6月9日交稿,等结束排版到印刷出来的话大概要两三个月的时间吧
非常感谢楼主,希望楼主的书有电子版,可以在kindle上看,快点出书吧,希望豆子的书里可以详细说说这个qml,因为我想用来开发企业级应用
现阶段不建议使用 QML 开发企业级应用。因为组件缺失太多,很容易增加开发复杂度,进而拖慢进度。
那豆子前辈觉得用什么写界面比较好呀, 用来开发erp的
看你的需求了,一般的 GUI 界面都是可以的吧。现在不是有 Java 的,要么你就用 Qt/C++ 也可以。像 ERP 这么复杂的界面,Qt Quick 肯定很复杂的
想问下楼主,我们公司准备开发一套客户端使用的是http协议,而且界面可能会要美化一下,请问一下这个是使用qt还是fc好点呢,快速。容易上手。开发周期短
话说还不大了解你说的 fc 是什么东西?具体还是看你的需求,如果要求跨平台的话,Qt 还是比较适合的。
呵呵,不好意思,少写了个M,是MFC,,
跨平台倒 是不用。之前以为要跨 平台准备用QT。。但不跨平台我也感觉QT好像比mfc要好。。
Qt 的设计要比 MFC 优秀,如果喜欢 Qt,使用 Qt 也是不错的。
QWidget的思路是用C++来实现高度抽象的绘图,所以使用了大量的设计模式,虽然达到了目的,但是造就了程序的复杂性。QWidget是越往底层走,越是发觉设计模式设计的精巧,但是要研究的代码和注释也越多越复杂,这真是上层开发人员所要的么?
QML和JavaScript其实提供了另一种思路,直接使用描述式的脚本,直接使用更加符合思维习惯的编程模型,代码即是注释。
从其他项目的发展来看,也有类似的趋势,Webkit是一个把设计模式和模板技术用得淋漓尽致的项目,现在谷歌却要在分裂出来 的Blink里面用JavaScript重写DOM等模块。
最近在学习QT,看到前辈很多好的文章,但是每次打开您的网站都很慢,所以想请问您的文章可以转载吗?谢谢。
不知道现在的速度如何?我这里测试还是挺快的。文章可以转载的,感谢支持!
弱弱的问一句,如果想做一个左边是菜单,右边是内容区的类爱奇艺播放器界面,该怎么写呢?
这个要定制界面的,可以参考一下网上的有关 360 界面的实现
最近才接触的Qt,差不多学了半个多月了,正愁找不到好的学习东西,一直在看一老外在youtube上的视频,内容有些陈旧了,没有新技术更新,而且无奈英语太烂,只能根据他写的代码了解个大概,有的时候,如果他不写代码的话,一直在那说,都不知道他说的是啥。。。只能是一边看,一边在网上找资料,有好几次都找到了前辈这里,真可以说是帮了我很大的忙,谢谢啦!如果有机会,我想以前辈的文章为材料,录制一套基础视频教程,这样的话以后想看视频学Qt的朋友终于也算是有中文教程了,每段视频都会介绍出处,不知道前辈是否同意
如果有时间的话可以做个视频试试啦,不过还是贵在坚持 ;-P
其中qml不能用于企业软件开发的原因说的不太准确,Qt5以前的quick1确实缺少组件、缺少桌面操作的部分支持。但Qt5开始的quick2已经获得了这方面的补充,特别是到现在的5.3版本。
目前的quick2已经足以开发企业软件,但是又一个问题:quick2采用了新的渲染方式,需要OpenGL的支持,而大多数企业办公电脑却不足以提供这方面的支持,这是致命的。
quick1要求低但适用性不好,quick2可以但要求高。结果quick目前只能更偏向于移动设备或者休闲类游戏的开发上,官方提供的示例或相关的博文都倾向于这点。
个人感觉即便是 Qt 5.3,开发企业应用的组件还是太少。企业应用大量使用 tree、复杂的 table,这两个组件 Qt Quick Controls 要么根本没有提供,要么提供的功能太弱,定制起来非常复杂。如果要自己从头实现一个 tree,恐怕也不是那么容易的事情。Qt Quick 2 也可以使用 ANGLE 的方式,这就绕过了 OpenGL,只要系统不要太旧,一般没有问题的。我曾在六年前的机器上运行过 ANGLE 版本的 Qt Quick 2,是没有问题的。如果超过六年的确也不保证了
那么是否可以将qml与c++方式一起使用来开发呢?复杂的控件用c++方式,然后将两者合起来?
当然可以啦!!可以互相调用的。
比如我用qml写个button,c++写个widget,怎么把这个button放到widget上去?
如果可以的话那真的可以简化许多编码啊
可以的,你可以在文档中搜索 Integrating QML and C++ 查看相关内容。
现在有哪台机器不支持OpenGL的?ANGLE 也可以的。
看了几天,c++与qml的交互集成这个链接说的比较好。
http://developer.blackberry.com/native/documentation/cascades/dev/integrating_cpp_qml/
各种资料还是得去国外网站找啊,就是英文看的头疼
楼主,如果你下一步能写一些Qt的应用例子,比如Qt动态绘制实时曲线图;局部放大缩小功能等等。我觉得对于Qt界朋友贡献将非常大,这个可以作为你Qt高级应用篇的文章。
这个也会仔细考虑的,感谢关注
我最近研究了下qt源码,有一些心得:qt源码中的gui部分和widget是分开来了,实质上qt源码最核心的就是Qt Core和Qt GUI,一个主要负责事件,一个负责呈现。用户其实根据这两部分接口也可以实现自己的widget甚至自己的Graphics View Framework。qt中的widget和Graphics View Framework的渲染引擎都是 Qt GUI中QPainter-> QPaintEngine->QPaintDevice,事件也都是依赖Qt Core.其本质区别是对于Qt Core和Qt GUI的组织管理调用的区别。
我想用他实现一个qq聊天框那样的编辑框,虽然TextArea支持富文本编辑,但是不能动态显示gif图,请问这个有什么解决办法吗?
可以考虑使用 QWebKit 直接写网页