前面的章节中,我们看到了作为输入元素的MouseArea,用于接收鼠标的输入。下面,我们再来介绍关于键盘输入的两个元素:TextInputTextEdit

TextInput是单行的文本输入框,支持验证器、输入掩码和显示模式等。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import QtQuick 2.0
 
Rectangle {
    width: 200
    height: 80
    color: "linen"
 
    TextInput {
        id: input1
        x: 8; y: 8
        width: 96; height: 20
        focus: true
        text: "Text Input 1"
    }
 
    TextInput {
        id: input2
        x: 8; y: 36
        width: 96; height: 20
        text: "Text Input 2"
    }
}

注意,我们这里放置了两个TextInput,用户可以通过点击输入框改变焦点。如果我们想支持键盘导航,可以添加KeyNavigation附加属性。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import QtQuick 2.0
 
Rectangle {
    width: 200
    height: 80
    color: "linen"
 
    TextInput {
        id: input1
        x: 8; y: 8
        width: 96; height: 20
        focus: true
        text: "Text Input 1"
        KeyNavigation.tab: input2
    }
 
    TextInput {
        id: input2
        x: 8; y: 36
        width: 96; height: 20
        text: "Text Input 2"
        KeyNavigation.tab: input1
    }
}

KeyNavigation是一个附加属性。当用户点击了指定的按键时,属性指定的组件就会获得焦点。附加属性类似于普通属性,但是又有所区别。普通的属性隶属于这个类型;附加属性一般用于修饰或补充目标类型。比如这里的KeyNavigation.tab并不是TextInput的普通属性,仅仅是用来说明TextInput的一种特征。附加属性的一般语法是类型.属性名,以此为例,类型就是KeyNavigation,属性名就是tab

QLineEdit不同,QML 的文本出入组件只有一个闪动的光标和用户输入的文本,没有边框等可视元素。因此,为了能够让用户意识到这是一个可输入元素,通常需要一些可视化修饰,比如绘制一个矩形框。当我们这么做的时候,创建一个完整的组件可能是更好的选择,只是要记得导出所需要的属性,以便外部使用。按照这种思路,我们创建一个组件:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// LineEdit.qml
 
import QtQuick 2.0
 
Rectangle {
    width: 96;
    height: input.height + 8
    color: "lightsteelblue"
    border.color: "gray"
 
    property alias text: input.text
    property alias input: input
 
    TextInput {
        id: input
        anchors.fill: parent
        anchors.margins: 4
        focus: true
    }
}

为了让外界可以直接设置TextInputtext属性,我们给这个属性声明了一个别名。同时,为了让外界可以访问到内部的textInput,我们将这个子组件也暴露出来。不过,从封装的角度而言,将实现细节暴露出去并不是一个好的设计,这要看暴露出来这个子组件的影响究竟有多大。然而这些都是关于设计的问题,需要具体问题具体分析,这里不再赘述。

下面我们可以将前面的例子修改成我们新创建的LineEdit组件:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import QtQuick 2.0
 
Rectangle {
    width: 200
    height: 80
    color: "linen"
 
    LineEdit {
        id: input1
        x: 8; y: 8
        width: 96; height: 20
        focus: true
        text: "Text Input 1"
        KeyNavigation.tab: input2
    }
 
    LineEdit {
        id: input2
        x: 8; y: 36
        width: 96; height: 20
        text: "Text Input 2"
        KeyNavigation.tab: input1
    }
}

只要将 LineEdit.qml 与 main.qml 放在同一目录下,我们就不需要额外的操作,即可在 main.qml 中直接使用LineEdit。运行结果如下:

现在再来试试键盘导航。这次无论怎么按键盘,焦点始终不会到input2。虽然我们在组件中添加了focus: true,可是不起作用。原因是,焦点被inputText的父组件Rectangle获得,然而,Rectangle不会将焦点转发给inputText。为了解决这一问题,QML提供了另外一个组件FocusScope

FocusScope接收到焦点时,会将焦点转发给最后一个设置了focus:true的子对象。所以,我们可以使用FocusScope重写LineEdit组件:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// LineEdit.qml
 
import QtQuick 2.0
 
FocusScope {
    width: 96;
    height: input.height + 8
    color: "lightsteelblue"
    border.color: "gray"
 
    property alias text: input.text
    property alias input: input
 
    TextInput {
        id: input
        anchors.fill: parent
        anchors.margins: 4
        focus: true
    }
}

这样修改过之后,我们就可以像之前的TextInput一样正常使用了。

TextEditTextInput非常类似,唯一区别是TextEdit是多行的文本编辑组件。与TextInput类似,TextEdit也没有一个可视化的显示,所以我们也需要自己绘制其显示区域。这些内容与前面代码几乎一样,这里不再赘述。

附加属性Keys类似于键盘事件,允许我们相应特定的按键按下事件。例如,我们可以利用方向键控制举行的位置,如下代码所示:

 
 
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
import QtQuick 2.0
 
DarkSquare {
    width: 400; height: 200
 
    GreenSquare {
        id: square
        x: 8; y: 8
    }
    focus: true
    Keys.onLeftPressed: square.x -= 8
    Keys.onRightPressed: square.x += 8
    Keys.onUpPressed: square.y -= 8
    Keys.onDownPressed: square.y += 8
    Keys.onPressed: {
        switch(event.key) {
            case Qt.Key_Plus:
                square.scale += 0.2
                break;
            case Qt.Key_Minus:
                square.scale -= 0.2
                break;
        }
    }
}

Qt 学习之路:输入元素的更多相关文章

  1. Qt 学习之路:元素布局

    上一章我们介绍了 QML 中用于定位的几种元素,被称为定位器.除了定位器,QML 还提供了另外一种用于布局的机制.我们将这种机制成为锚点(anchor).锚点允许我们灵活地设置两个元素的相对位置.它使 ...

  2. Qt 学习之路 2(51):布尔表达式树模型

    Qt 学习之路 2(51):布尔表达式树模型 豆子 2013年5月15日 Qt 学习之路 2 17条评论 本章将会是自定义模型的最后一部分.原本打算结束这部分内容,不过实在不忍心放弃这个示例.来自于 ...

  3. Qt 学习之路 2(43):QStringListModel

    Qt 学习之路 2(43):QStringListModel 豆子 2013年2月13日 Qt 学习之路 2 38条评论 上一章我们已经了解到有关 list.table 和 tree 三个最常用的视图 ...

  4. Qt 学习之路 2(38):存储容器

    Qt 学习之路 2(38):存储容器 豆子 2013年1月14日 Qt 学习之路 2 38条评论 存储容器(containers)有时候也被称为集合(collections),是能够在内存中存储其它特 ...

  5. 《Qt 学习之路 2》目录

    <Qt 学习之路 2>目录 <Qt 学习之路 2>目录  豆子  2012年8月23日  Qt 学习之路 2  177条评论 <Qt 学习之路 2>目录 序 Qt ...

  6. Qt 学习之路 2(76):QML 和 QtQuick 2

    Home / Qt 学习之路 2 / Qt 学习之路 2(76):QML 和 QtQuick 2 Qt 学习之路 2(76):QML 和 QtQuick 2  豆子  2013年12月18日  Qt ...

  7. Qt 学习之路 2(72):线程和事件循环

    Qt 学习之路 2(72):线程和事件循环 <理解不清晰,不透彻>  --  有需求的话还需要进行专题学习  豆子  2013年11月24日  Qt 学习之路 2  34条评论 前面一章我 ...

  8. Qt 学习之路 2(69):进程

    Qt 学习之路 2(69):进程 豆子 2013年11月9日 Qt 学习之路 2 15条评论 进程是操作系统的基础之一.一个进程可以认为是一个正在执行的程序.我们可以把进程当做计算机运行时的一个基础单 ...

  9. Qt 学习之路 2(60):使用 DOM 处理 XML

    Qt 学习之路 2(60):使用 DOM 处理 XML  豆子  2013年8月3日  Qt 学习之路 2  9条评论 DOM 是由 W3C 提出的一种处理 XML 文档的标准接口.Qt 实现了 DO ...

  10. Qt 学习之路 2(59):使用流处理 XML

    Qt 学习之路 2(59):使用流处理 XML 豆子 2013年7月25日 Qt 学习之路 2 18条评论 本章开始我们将了解到如何使用 Qt 处理 XML 格式的文档. XML(eXtensible ...

随机推荐

  1. RPMForge——Quick Start build system

    How to setup multimedia on CentOS-5 CentOS ships with basic sound support for audio content encoded ...

  2. iOS: 学习笔记, 值与引用类型(译自: https://developer.apple.com/swift/blog/ Aug 15, 2014 Value and Reference Types)

    值和引用类型 Value and Reference Types 在Swift中,有两种数据类型. 一是"值类型"(value type), 它是每一个实例都保存有各自的数据,通常 ...

  3. failure injection

    (1)malloc穷尽的情况: 假设下面的代码是测试代码,里面含有被测函数fmalloc,其中含有一个malloc语句,在一般情况下,是很难走到malloc失败的分支的,因为很难模拟系统内存耗尽的情况 ...

  4. Window7 下开发php扩展

    一.首先查看phpinfo() 信息PHP Version 5.4.34Zend Extension Build     API220100525,TS,VC9 PHP Extension Build ...

  5. 更新wix installer里的Guid

    string path=@"\Setup\Installer"; var files = Directory.GetFiles(path); foreach (var item i ...

  6. ARCH Linux pacman 包管理器出错总结

    最在使用ARCH的时候使用命令: sudo pacman -S Ruby 终端报错: error: could not open file /var/lib/pacman/sync/apricity- ...

  7. [UOJ 74] 【UR #6】破解密码

    题目链接:UOJ - 74 题目分析 题目中,将字符串 S 的第一个字符移到末尾,其他字符向前移动一个位置,f(S) 就从 Hi 变成了 Hi+1. 我们分析一下这个过程:假设第一个字符为 c, (H ...

  8. 7 Tools for Data Visualization in R, Python, and Julia

    7 Tools for Data Visualization in R, Python, and Julia Last week, some examples of creating visualiz ...

  9. 通过 DevOps 整合开发和应用安全管道

    [编者按]作者 Aaron Volkmann 是 CERT Division 高级研究员,通过提出了一种集成安全系统到 CI/CD 的方法,让机构保持快速部署到生产环境能力的同时,也大幅度降低安全隐患 ...

  10. Java语言基础(五) Java原始数据类型的分类以及数据范围

    Java原始数据类型的分类以及数据范围 1.基本数据类型分为:整型(byte, short, int, long),浮点型(float, double),字符型(char),布尔型(boolean) ...