MacOS下Qt+qml+Android开发系列:1、认识常用控件

248 阅读12分钟

一、前言

上一次我们搭建好了MacOS下的Qt6+Android开发环境,而且创建了简单的helloworld项目进行测试,官方是强烈推荐qml进行开发的,我试了一下确实还可以,但是由于是新手,虽然有一些js和前端的基础,但是还是感觉Qt crearot以及qml写起来不顺手,主要还是新手不熟悉控件的相关属性,导致写起来不畅快,然后正好在掘金发现了AI IDE工具Trae,我初步试了下确实很不错,新手对于一些控件不熟悉也可以快速补全,相当于vscode+代码智能补全+deepseek,确实写起来代码很流畅,这里正好借着学习qml开发Android程序的过程来使用一下。

二、qml实现常用控件

直接在trae上问常见的控件,然后我们一个个再来熟悉和实践:

1. 窗口控件

  • Window:代表一个顶级窗口,可用于创建应用程序的主窗口。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    width: 320
    height: 720
    visible: true
    title: qsTr("Hello World")
}

在 QML 中,窗口控件(如 Window)有许多常见的属性可以设置,下面为你介绍一些常用属性及其示例:

1.1. 尺寸属性

  • width** 和 **height:用于设置窗口的宽度和高度,单位为像素。
  • 注意:width 和 height 属性使用的单位是像素(px),而非设备独立像素(dp)。所以 width: 320 和 height: 720 代表的是 320 像素和 720 像素,所以结合设计图时要注意这一点。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    width: 400
    height: 600
    // ... existing code ...
}

1.2. 可见性属性

  • visible:用于控制窗口是否可见,值为 truefalse
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    visible: true
    // ... existing code ...
}

1.3. 标题属性

  • title:用于设置窗口的标题,值为字符串。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    title: qsTr("新的窗口标题")
    // ... existing code ...
}

1.4. 背景颜色属性

  • color:用于设置窗口的背景颜色,可以使用颜色名称、十六进制值等。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    color: "lightblue"
    // ... existing code ...
}

1.5. 最小和最大尺寸属性

  • minimumWidthminimumHeightmaximumWidth** 和 **maximumHeight:用于设置窗口的最小和最大宽度、高度。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    minimumWidth: 200
    minimumHeight: 300
    maximumWidth: 800
    maximumHeight: 600
    // ... existing code ...
}

1.6. 模态属性

  • modality:用于设置窗口的模态行为,控制窗口是否阻塞其他窗口的输入。常见值有 Qt.NonModal(非模态)、Qt.WindowModal(窗口模态)和 Qt.ApplicationModal(应用程序模态)。
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick 2.12

Window {
    // ... existing code ...
    modality: Qt.WindowModal
    // ... existing code ...
}

1.7. 测试效果

写注释都有AI提示:(投屏的使用scrcpy,brew install scrcpy安装即可)

2. 文本控件

  • Text:用于显示静态文本。
Text {
    text: "这是一段文本"
    font.pixelSize: 20
    color: "red"
}

在 QML 里,文本控件(Text)有许多常见属性,下面为你详细介绍:

2.1. 文本内容属性

  • text:用于设置或获取文本控件显示的内容。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    Text {
        text: "这是一段文本"
    }
    // ... existing code ...
}

2.2. 字体属性

  • font.family:设置字体名称。
  • font.pixelSize:设置字体大小,单位为像素。
  • font.bold:设置字体是否加粗,值为 truefalse
  • font.italic:设置字体是否倾斜,值为 truefalse
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    Text {
        text: "自定义字体文本"
        font.family: "Arial"
        font.pixelSize: 20
        font.bold: true
        font.italic: true
    }
    // ... existing code ...
}

2.3. 颜色属性

  • color:设置文本的颜色,可以使用颜色名称、十六进制值等。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    Text {
        text: "红色文本"
        color: "red"
    }
    // ... existing code ...
}

2.4. 对齐属性

  • horizontalAlignment:设置文本的水平对齐方式,常见值有 Text.AlignLeftText.AlignHCenterText.AlignRight 等。
  • verticalAlignment:设置文本的垂直对齐方式,常见值有 Text.AlignTopText.AlignVCenterText.AlignBottom 等。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    Text {
        text: "居中对齐文本"
        width: 200
        height: 50
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }
    // ... existing code ...
}

2.5. 换行属性

  • wrapMode:设置文本的换行模式,常见值有 Text.NoWrap(不换行)、Text.WordWrap(按单词换行)等。
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    Text {
        text: "这是一段很长的文本,可能需要换行显示。"
        width: 100
        wrapMode: Text.WordWrap
    }
    // ... existing code ...
}

2.6. 可见性属性

  • visible:控制文本控件是否可见,值为 truefalse
import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    // ... existing code ...
    Text {
        text: "隐藏或显示的文本"
        visible: false
    }
    // ... existing code ...
}

2.7. 测试效果

3. 按钮控件

注意:按钮需要导入如下模块

import QtQuick.Controls 2.12
  • Button:可点击的按钮,通常用于触发操作。
import QtQuick.Controls 2.12

Button {
    text: "点击我"
    onClicked: {
        console.log("按钮被点击了")
    }
}

在 QML 里,按钮控件(通常使用 Button 组件,需导入 QtQuick.Controls 模块)有许多常见属性,下面为你详细介绍并给出示例:

3.1. 文本属性

  • text:用于设置按钮上显示的文本内容。
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

// ... existing code ...
Button {
    text: "点击我"
}
// ... existing code ...

3.2. 尺寸属性

  • width** 和 **height:用于设置按钮的宽度和高度。
// ... existing code ...
Button {
    text: "自定义尺寸按钮"
    width: 150
    height: 50
}
// ... existing code ...

3.3. 状态属性

  • enabled:控制按钮是否可用,值为 truefalse。当设置为 false 时,按钮不可点击。
  • pressed:表示按钮是否被按下,通常用于监听按钮按下和释放的状态变化。
// ... existing code ...
Button {
    text: "禁用按钮"
    enabled: false
}

Button {
    text: "状态监听按钮"
    onPressed: console.log("按钮被按下")
    onReleased: console.log("按钮被释放")
}
// ... existing code ...

3.4. 样式属性

  • background:用于自定义按钮的背景,可以使用 Rectangle 等组件。
  • contentItem:用于自定义按钮的内容,例如文本、图标等。
// ... existing code ...
Button {
    width: 100
    height: 40
    background: Rectangle {
        color: pressed ? "gray" : "blue"
        radius: 5
    }
    contentItem: Text {
        text: parent.text
        color: "white"
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }
}
// ... existing code ...

3.5. 信号与槽属性

  • onClicked:按钮被点击时触发的信号,可关联相应的处理函数。
// ... existing code ...
Button {
    text: "触发事件按钮"
    onClicked: {
        console.log("按钮被点击,执行相应操作")
        // 可以在这里添加其他操作
    }
}
// ... existing code ...

3.6. 测试效果

4. 输入控件

  • TextField:单行文本输入框。
import QtQuick.Controls 2.12

TextField {
    placeholderText: "请输入文本"
    onTextChanged: {
        console.log("输入的文本是: " + text)
    }
}
  • TextArea:多行文本输入框。
import QtQuick.Controls 2.12

TextArea {
    placeholderText: "请输入多行文本"
    width: 200
    height: 100
}

在 QML 里,常见的输入控件有 TextField(单行输入框)和 TextArea(多行输入框),下面为你详细介绍它们的常用属性。

4.1. TextField 常用属性

文本内容相关
  • text:用于设置或获取输入框当前的文本内容。
  • placeholderText:当输入框为空时显示的提示文本。
// ... existing code ...
TextField {
    id: singleInput
    text: "默认文本"
    placeholderText: "请输入内容"
}
// ... existing code ...
输入显示相关
  • echoMode:控制文本的显示模式,常见值有 TextField.Normal(正常显示)、TextField.Password(密码模式,显示星号)等。
// ... existing code ...
TextField {
    id: passwordInput
    echoMode: TextField.Password
    placeholderText: "请输入密码"
}
// ... existing code ...
输入验证相关
  • validator:用于限制输入的内容,可使用 IntValidatorDoubleValidatorRegExpValidator 等。
// ... existing code ...
TextField {
    id: numberInput
    validator: IntValidator {
        bottom: 0
        top: 100
    }
    placeholderText: "请输入 0 - 100 之间的整数"
}
// ... existing code ...
信号相关
  • onTextChanged:当输入框的文本内容发生变化时触发。
// ... existing code ...
TextField {
    id: changeInput
    onTextChanged: {
        console.log("输入内容已变为: " + text)
    }
}
// ... existing code ...

4.2. TextArea 常用属性

文本内容相关
  • text:用于设置或获取文本区域当前的文本内容。
  • placeholderText:当文本区域为空时显示的提示文本。
// ... existing code ...
TextArea {
    id: multiInput
    text: "默认多行文本"
    placeholderText: "请输入多行内容"
}
// ... existing code ...
滚动相关
  • scrollBarPolicy:控制滚动条的显示策略,常见值有 Qt.ScrollBarAsNeeded(按需显示)、Qt.ScrollBarAlwaysOn(始终显示)等。
// ... existing code ...
TextArea {
    id: scrollableArea
    scrollBarPolicy: Qt.ScrollBarAsNeeded
    width: 200
    height: 100
}
// ... existing code ...
只读属性
  • readOnly:设置文本区域是否为只读模式,值为 truefalse
// ... existing code ...
TextArea {
    id: readOnlyArea
    text: "这是只读文本"
    readOnly: true
}
// ... existing code ...

4.3. 测试效果

5. 列表控件

  • ListView:用于显示列表数据。
import QtQuick 2.12
import QtQuick.Controls 2.12

ListView {
    width: 200
    height: 200
    model: ["Item 1", "Item 2", "Item 3"]
    delegate: Text {
        text: modelData
    }
}

在 QML 里,常见的列表控件有 ListViewGridViewRepeater 等,下面为你介绍这些列表控件的常用属性。

5.1. ListView 属性

数据模型属性
  • model:用于指定列表的数据模型,可以是数组、ListModel 等。
ListView {
    // ... existing code ...
    model: ["Item 1", "Item 2", "Item 3"]
    // ... existing code ...
}
委托属性
  • delegate:定义列表项的外观和行为,通常使用 Component 或直接在 ListView 中定义。
ListView {
    // ... existing code ...
    delegate: Text {
        text: modelData
    }
    // ... existing code ...
}
滚动属性
  • flickableDirection:指定列表的滚动方向,常见值有 Flickable.VerticalFlick(垂直滚动)和 Flickable.HorizontalFlick(水平滚动)。
  • boundsBehavior:控制列表滚动到边界时的行为。
ListView {
    // ... existing code ...
    flickableDirection: Flickable.VerticalFlick
    boundsBehavior: Flickable.StopAtBounds
    // ... existing code ...
}

5.2. GridView 属性

布局属性
  • cellWidth** 和 **cellHeight:指定网格中每个单元格的宽度和高度。
  • columns:指定网格的列数。
GridView {
    // ... existing code ...
    cellWidth: 100
    cellHeight: 100
    columns: 3
    // ... existing code ...
}
数据模型和委托属性

GridView 同样使用 modeldelegate 属性,用法与 ListView 类似。

GridView {
    // ... existing code ...
    model: ["Item 1", "Item 2", "Item 3"]
    delegate: Text {
        text: modelData
    }
    // ... existing code ...
}

5.3. Repeater 属性

数据模型属性
  • model:指定要重复的数据源,可以是数组、ListModel 等。
Column {
    Repeater {
        // ... existing code ...
        model: ["Item 1", "Item 2", "Item 3"]
        delegate: Text {
            text: modelData
        }
        // ... existing code ...
    }
}

5.4. 测试效果

6. 图像控件

  • Image:用于显示图片。
Image {
    source: "image.png"
    width: 100
    height: 100
}

在 QML 里,图像控件主要是 Image 组件,下面为你介绍它的常用属性:

6.1. 图像源属性

  • source:用于指定要显示的图像文件的路径,可以是本地文件路径、网络 URL 或者资源路径。
// ... existing code ...
Image {
    source: "images/logo.png" // 本地文件路径
    // source: "https://example.com/image.jpg" // 网络 URL
}
// ... existing code ...

6.2. 尺寸属性

  • width** 和 **height:设置图像控件的宽度和高度。
  • fillMode:控制图像如何填充控件区域,常见值有 Image.Stretch(拉伸图像)、Image.PreserveAspectFit(保持宽高比适应控件)、Image.PreserveAspectCrop(保持宽高比裁剪图像)等。
// ... existing code ...
Image {
    source: "images/logo.png"
    width: 200
    height: 200
    fillMode: Image.PreserveAspectFit
}
// ... existing code ...

6.3. 对齐属性

  • horizontalAlignment** 和 **verticalAlignment:控制图像在控件内的水平和垂直对齐方式。
// ... existing code ...
Image {
    source: "images/logo.png"
    width: 200
    height: 200
    horizontalAlignment: Image.AlignHCenter
    verticalAlignment: Image.AlignVCenter
}
// ... existing code ...

6.4. 加载状态属性

  • status:表示图像的加载状态,常见值有 Image.Null(未加载)、Image.Ready(已加载)、Image.Loading(正在加载)、Image.Error(加载出错)。
  • onStatusChanged:图像加载状态改变时触发的信号,可以用于处理加载成功或失败的情况。
// ... existing code ...
Image {
    source: "images/logo.png"
    onStatusChanged: {
        if (status === Image.Ready) {
            console.log("图像加载成功")
        } else if (status === Image.Error) {
            console.log("图像加载失败: " + errorString)
        }
    }
}
// ... existing code ...

6.5. 缓存属性

  • cache:控制是否缓存图像,值为 truefalse。开启缓存可以提高图像的加载速度。
// ... existing code ...
Image {
    source: "images/logo.png"
    cache: true
}
// ... existing code ...

6.6. 测试效果

7. 布局控件

  • Row:将子项水平排列。
import QtQuick.Controls 2.12

Row {
    spacing: 10
    Button { text: "按钮1" }
    Button { text: "按钮2" }
}
  • Column:将子项垂直排列。
import QtQuick.Controls 2.12

Column {
    spacing: 10
    Button { text: "按钮1" }
    Button { text: "按钮2" }
}

在 QML 里,布局控件用于管理子控件的位置和大小,常见的布局控件有 RowColumnGridFlow 等。下面为你介绍这些布局控件的常用属性:

7.1. Row 布局控件属性

Row 用于将子控件水平排列。

间距属性
  • spacing:设置子控件之间的水平间距。
import QtQuick 2.12
import QtQuick.Controls 2.12

// ... existing code ...
Row {
    spacing: 10
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
}
// ... existing code ...
对齐属性
  • horizontalAlignment:设置子控件在水平方向上的对齐方式。
  • verticalAlignment:设置子控件在垂直方向上的对齐方式。
// ... existing code ...
Row {
    horizontalAlignment: Qt.AlignHCenter
    verticalAlignment: Qt.AlignVCenter
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
}
// ... existing code ...

7.2. Column 布局控件属性

Column 用于将子控件垂直排列。

间距属性
  • spacing:设置子控件之间的垂直间距。
// ... existing code ...
Column {
    spacing: 10
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
}
// ... existing code ...
对齐属性
  • horizontalAlignment:设置子控件在水平方向上的对齐方式。
  • verticalAlignment:设置子控件在垂直方向上的对齐方式。
// ... existing code ...
Column {
    horizontalAlignment: Qt.AlignHCenter
    verticalAlignment: Qt.AlignVCenter
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
}
// ... existing code ...

7.3. Grid 布局控件属性

Grid 用于将子控件排列成网格形式。

网格属性
  • columns:设置网格的列数。
  • rows:设置网格的行数。
  • cellWidth:设置每个网格单元格的宽度。
  • cellHeight:设置每个网格单元格的高度。
// ... existing code ...
Grid {
    columns: 2
    cellWidth: 100
    cellHeight: 50
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
    Button { text: "按钮 3" }
    Button { text: "按钮 4" }
}
// ... existing code ...
间距属性
  • spacing:设置网格单元格之间的水平和垂直间距。也可以分别使用 horizontalSpacingverticalSpacing 来单独设置。
// ... existing code ...
Grid {
    columns: 2
    spacing: 10
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
    Button { text: "按钮 3" }
    Button { text: "按钮 4" }
}
// ... existing code ...

7.4. Flow 布局控件属性

Flow 会根据可用空间自动排列子控件,当一行或一列空间不足时,会自动换行或换列。

流向属性
  • flow:设置子控件的排列方向,常见值有 Flow.LeftToRight(从左到右)和 Flow.TopToBottom(从上到下)。
// ... existing code ...
Flow {
    flow: Flow.LeftToRight
    spacing: 10
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
    Button { text: "按钮 3" }
    Button { text: "按钮 4" }
}
// ... existing code ...
间距属性
  • spacing:设置子控件之间的水平和垂直间距。也可以分别使用 horizontalSpacingverticalSpacing 来单独设置。
// ... existing code ...
Flow {
    flow: Flow.LeftToRight
    horizontalSpacing: 10
    verticalSpacing: 10
    Button { text: "按钮 1" }
    Button { text: "按钮 2" }
    Button { text: "按钮 3" }
    Button { text: "按钮 4" }
}
// ... existing code ...

7.5. 测试效果

三、最后

这个是最终的qml代码:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

//窗口控件
Window {
  //1、窗口尺寸属性
  width: 720
  height: 1440
  //2、窗口标题属性
  visible: true
  //3、窗口背景色属性
  color: "white"
  //4、窗口标题属性
  title: qsTr("Hello World")
  //5、窗口透明度属性
  opacity: 0.5

  Column {
    spacing: 10
    Text {
      id: helloText
      // 1、文字内容属性
      text: qsTr("Hello World")
      // 2、字体属性
      font.pixelSize: 30
      // 3、颜色属性
      color: "red"
      // 4、对齐方式属性
      horizontalAlignment: Text.AlignHCenter
      verticalAlignment: Text.AlignRight
      // 5、换行方式属性
      wrapMode: Text.WordWrap
      // 6、隐藏属性
      visible: true
    }

    Button {
      id: helloButton
      // 1、文字内容属性
      text: qsTr("Hello Button")
      // 2、尺寸属性
      width: 200
      height: 50
      // 3、状态属性
      enabled: true
      // 4、样式属性
      background: Rectangle {
        color: "blue"
        border.color: "black"
        border.width: 2
        radius: 10
      }
      // 5、信号槽属性
      onClicked: {
        helloText.text = qsTr("Hello Button Clicked")
      }
    }

    TextField {
      id: helloTextField
      // 1、文字内容属性
      placeholderText: qsTr("请输入内容:")
      // 2、尺寸属性
      width: 200
      height: 50
      // 3、输入显示模式
      echoMode: TextField.Normal
      // 4、信号相关
      onTextChanged: {
        helloText.text = helloTextField.text
      }
    }

    ListView {
      id: helloListView
      // 1、尺寸属性
      width: 200
      height: 200
      // 2、模型属性
      model: [
        { text: qsTr("Hello ListView") },
        { text: qsTr("Hello ListView 1") },
        { text: qsTr("Hello ListView 2") }
      ]
      // 3、委托属性
      delegate: Text {
        text: modelData.text
        font.pixelSize: 20
        color: "black"
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
        wrapMode: Text.WordWrap
      }
      // 4、滚动属性
      flickableDirection: Flickable.VerticalFlick
      boundsBehavior: Flickable.StopAtBounds
      // 5、信号相关
      onCurrentIndexChanged: {
        helloText.text = helloListView.model[helloListView.currentIndex].text
      }
    }

    Image {
      id: helloImage
      // 1、图片属性
      // source: "qrc:/images/hello.png"
      source: "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg"
      // 2、尺寸属性
      width: 300
      height: 200
      // 3、对齐方式属性
      horizontalAlignment: Image.AlignHCenter
            verticalAlignment: Image.AlignVCenter
            // 4、加载状态属性
            // 5、缓存属性
            cache: false
            // 6、信号相关
            onStatusChanged: {
                helloText.text = helloImage.status
            }
        }
    }
}

接下来,我们再实现一下常见的滚动页面、左右切换页面、按钮按下切换页面这类的页面切换功能。