创建第一个 Qt Quick 应用从零到窗口弹出(四)

适合人群: 已安装 Qt,想动手跑出第一个真实程序的新手

前言

前几篇我们了解了 Qt 的产品体系和构建工具,现在终于到了动手的时刻。

本文目标只有一个:在 Qt Creator 里创建一个 Qt Quick 项目,添加几个 QML 组件,让它成功运行起来。不追求完美,只追求跑通------跑通之后,一切都会变得具体。


一、Qt Quick 是什么?

在动手之前,先用一句话区分两个容易混淆的概念:

  • QML:一种声明式编程语言,描述"界面长什么样、怎么交互"
  • Qt Quick:基于 QML 的 UI 框架,提供了矩形、图片、文本、动画等一系列可直接使用的视觉元素

可以把 QML 理解为语言,Qt Quick 理解为用这门语言写成的标准组件库。写 Qt Quick 应用,本质上就是在写 QML 代码。


二、在 Qt Creator 中新建项目

第一步:打开新建项目向导

启动 Qt Creator,点击欢迎界面的 "Create Project" ,或菜单 File → New Project

第二步:选择项目模板

在模板列表中选择:

scss 复制代码
Application (Qt)
└── Qt Quick Application

点击 Choose...

第三步:填写项目信息

字段 填写内容
Name MyFirstApp(不要有空格和中文)
Location 选择一个路径(避免中文路径)

点击 Next

第四步:选择构建系统

选择 CMake (Qt 6 推荐,与上一篇一致),点击 Next

第五步:选择 Qt 版本

选择你安装的 Qt 版本(如 Qt 6.7.0),点击 Next ,再点击 Finish

项目创建完成,Qt Creator 会自动打开生成的文件。


三、认识自动生成的项目结构

创建完成后,左侧项目面板显示:

css 复制代码
MyFirstApp
├── CMakeLists.txt       ← 构建配置文件
└── Main.qml             ← 主界面文件
    main.cpp             ← C++ 入口文件

main.cpp --- 程序入口

arduino 复制代码
#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    const QUrl url(u"qrc:/MyFirstApp/Main.qml"_s);
    QObject::connect(
        &engine,
        &QQmlApplicationEngine::objectCreationFailed,
        &app,
        [](const QUrl &url) {
            qWarning() << "Failed to load:" << url;
            QCoreApplication::exit(-1);
        },
        Qt::QueuedConnection);

    engine.load(url);

    return app.exec();
}

这个文件基本不需要修改。它做了三件事:

  1. 创建 QGuiApplication 应用实例(管理整个程序的生命周期)
  2. 创建 QQmlApplicationEngine 引擎(负责加载和运行 QML)
  3. 加载 Main.qml 作为根界面,启动事件循环

Main.qml --- 主界面

arduino 复制代码
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
}

这就是你的第一个窗口。现在它是空的,接下来我们往里面加内容。


四、第一次运行

点击左下角绿色三角形 Run (或按 Ctrl+R)。

等待片刻,一个 640×480 的空白窗口应该出现在屏幕上------标题栏显示"Hello World"。

恭喜,Qt Quick 应用跑起来了。

如果没有弹出窗口,检查底部 "Compile Output" 面板,查看报错信息。最常见的问题是 Kit 未正确配置,回到 Preferences → Kits 检查编译器是否有绿色对勾。


五、添加第一个 QML 组件:文本

打开 Main.qml,在 ApplicationWindow 内部添加一个 Text 组件:

less 复制代码
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Text {
        anchors.centerIn: parent
        text: "你好,Qt Quick!"
        font.pixelSize: 28
        color: "#333333"
    }
}

Ctrl+R 重新运行,窗口中央会出现文字"你好,Qt Quick!"。

解析这段代码

  • anchors.centerIn: parent:将这个元素居中于父元素(即窗口)
  • font.pixelSize: 28:字体大小 28 像素
  • color: "#333333":深灰色,支持十六进制颜色值

六、添加按钮和交互

光显示文字还不够,加一个按钮,点击时改变文字内容:

less 复制代码
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Column {
        anchors.centerIn: parent
        spacing: 20

        Text {
            id: myText
            anchors.horizontalCenter: parent.horizontalCenter
            text: "你好,Qt Quick!"
            font.pixelSize: 28
            color: "#333333"
        }

        Button {
            anchors.horizontalCenter: parent.horizontalCenter
            text: "点我"
            onClicked: {
                myText.text = "按钮被点击了!"
                myText.color = "#1D9E75"
            }
        }
    }
}

运行后点击按钮,文字会变成绿色的"按钮被点击了!"。

新增知识点

Column :垂直排列子元素的布局容器,spacing: 20 设置子元素间距为 20 像素。

id: myText:给元素取一个唯一标识符,方便其他地方引用它。

onClicked :按钮的点击信号处理器。Qt Quick 中所有交互都通过信号和处理器实现------信号名前加 on 就是对应的处理器名称。


七、添加输入框:实现实时文字同步

再进一步,用 TextField 实现输入框内容与文本的实时同步:

less 复制代码
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Column {
        anchors.centerIn: parent
        spacing: 20
        width: 300

        TextField {
            id: inputField
            width: parent.width
            placeholderText: "在这里输入内容..."
            font.pixelSize: 16
        }

        Text {
            width: parent.width
            text: inputField.text !== "" ? inputField.text : "等待输入..."
            font.pixelSize: 24
            color: "#333333"
            horizontalAlignment: Text.AlignHCenter
            wrapMode: Text.Wrap
        }
    }
}

运行后在输入框里打字,下方文字会实时跟随变化。

核心概念:属性绑定

arduino 复制代码
text: inputField.text !== "" ? inputField.text : "等待输入..."

这行代码展示了 QML 最重要的特性之一------属性绑定text 的值不是一次性赋值,而是始终保持与 inputField.text 的动态关联。只要输入框内容变化,这里的文字自动更新,无需手动监听事件。

这是 QML 与传统命令式 UI 编程最大的区别,也是 QML 代码简洁的根本原因。


八、添加图片资源

在项目中显示一张图片需要两步:把图片加入项目,然后在 QML 中引用。

第一步:添加图片文件

将图片文件(如 logo.png)复制到项目目录下,例如放在 images/ 子目录中。

第二步:在 CMakeLists.txt 中注册

打开 CMakeLists.txt,在 qt_add_qml_module 中添加:

scss 复制代码
qt_add_qml_module(MyFirstApp
    URI MyFirstApp
    VERSION 1.0
    QML_FILES
        Main.qml
    RESOURCES
        images/logo.png
)

第三步:在 QML 中使用

yaml 复制代码
Image {
    anchors.horizontalCenter: parent.horizontalCenter
    source: "images/logo.png"
    width: 120
    height: 120
    fillMode: Image.PreserveAspectFit
}

fillMode: Image.PreserveAspectFit 表示保持图片原始宽高比进行缩放,不会拉伸变形。


九、弹出对话框

Qt Quick Controls 提供了现成的弹窗组件:

yaml 复制代码
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Button {
        anchors.centerIn: parent
        text: "显示弹窗"
        onClicked: dialog.open()
    }

    Dialog {
        id: dialog
        anchors.centerIn: parent
        title: "提示"
        modal: true

        Label {
            text: "这是一个弹出对话框!"
        }

        standardButtons: Dialog.Ok
    }
}

modal: true 表示弹窗为模态------弹出时用户必须先关闭它才能操作其他界面元素。


十、完整示例:把以上内容整合

yaml 复制代码
import QtQuick
import QtQuick.Controls

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    title: qsTr("我的第一个 Qt Quick 应用")

    Column {
        anchors.centerIn: parent
        spacing: 16
        width: 320

        Text {
            anchors.horizontalCenter: parent.horizontalCenter
            text: "Qt Quick 入门示例"
            font.pixelSize: 22
            font.bold: true
            color: "#222222"
        }

        TextField {
            id: nameInput
            width: parent.width
            placeholderText: "输入你的名字"
            font.pixelSize: 15
        }

        Button {
            width: parent.width
            text: "打招呼"
            onClicked: {
                if (nameInput.text !== "") {
                    greetDialog.open()
                }
            }
        }
    }

    Dialog {
        id: greetDialog
        anchors.centerIn: parent
        title: "你好!"
        modal: true

        Label {
            text: "欢迎来到 Qt Quick," + nameInput.text + "!"
            font.pixelSize: 16
        }

        standardButtons: Dialog.Ok
    }
}

运行后,在输入框填写名字,点击"打招呼",弹出包含姓名的问候对话框。


十一、常见问题

Q:修改 QML 后不需要重新编译吗?

QML 文件的修改通常不需要完整重新编译,Qt Creator 的 QML 热重载功能可以在不重启应用的情况下刷新界面。点击运行时工具栏的"重新加载 QML"按钮即可。

但修改 CMakeLists.txt 或 C++ 文件后,必须重新编译。

Q:anchors.centerIn: parentanchors.horizontalCenter: parent.horizontalCenter 有什么区别?

  • anchors.centerIn: parent:水平 + 垂直都居中
  • anchors.horizontalCenter: parent.horizontalCenter:只水平居中,垂直位置不受影响

Q:qsTr() 是什么?

qsTr() 是 Qt 的国际化函数,标记这段文字需要翻译。即使现在不做多语言支持,养成用 qsTr() 包裹用户可见字符串的习惯,以后国际化会容易很多。


十二、下一步

现在你已经能创建窗口、添加文本、处理点击事件、使用输入框和弹窗了。接下来建议:

  1. Introduction to QML --- 系统学习 QML 语法,理解属性绑定、信号、组件的完整概念
  2. Qt Quick vs. Widgets --- 了解什么场景用 Qt Quick,什么场景用 Qt Widgets
  3. Positioners and Layouts --- 学习更强大的布局方式,让 UI 适配不同屏幕尺寸

总结

组件 用途
ApplicationWindow 应用主窗口容器
Text 显示文字
Button 可点击按钮,onClicked 处理点击
TextField 单行文本输入框
Column 垂直排列子元素
Image 显示图片
Dialog 弹出对话框
anchors 定位系统,控制元素位置
属性绑定 a: b.value 让属性自动跟随另一个属性变化
相关推荐
HelloReader2 小时前
Qt 项目构建入门CMake 完全指南(三)
前端
用户908324602732 小时前
Spring AI + RAG + SSE 实现带搜索来源的智能问答完整方案
前端·后端
GISer_Jing2 小时前
阿里开源纯前端浏览器自动化 PageAgent,[特殊字符] 浏览器自动化变天啦?
前端·人工智能·自动化·aigc·交互
清风徐来QCQ2 小时前
js中的模板字符串
开发语言·前端·javascript
成都渲染101云渲染66662 小时前
Houdini+Blender高效渲染方案(高配算力+全渲染器兼容)
前端·系统架构
SuperEugene3 小时前
Vue3 + Element Plus 表格实战:批量操作、行内编辑、跨页选中逻辑统一|表单与表格规范篇
开发语言·前端·javascript
极梦网络无忧3 小时前
基于 Vite + Vue3 的组件自动注册功能
前端·javascript·vue.js
Predestination王瀞潞3 小时前
5.4.3 通信->WWW万维网内容访问标准(W3C):WWW(World Wide Web) 协议架构(分层)
前端·网络·网络协议·架构·www
爱学习的程序媛3 小时前
【Web前端】优化Core Web Vitals提升用户体验
前端·ui·web·ux·用户体验