当前位置: 首页 > news >正文

【qml入门】在qml项目上加入用户登录qml页面(包含源码)

前言

        参照QT项目做一个qml项目并不复杂,先从“在主框架上加一个页面”开始吧,方便初学者构建自己的qml项目。本人也有分享类似的QT项目博文(借鉴此博文的风格来分享):

【QT入门到晋级】拿别人的QT项目,加入用户登录页面

一、创建一个qml项目

完成以上傻瓜式的操作之后,我们在qtcreator可以看到3个能打开的文件

.pro文件,与qt项目相比,有如下变化

main.cpp文件,与qt项目相比,有如下变化

qt的main(),是直接调用w.show();来显示界面,而qml的main(),需要通过以下5步来显示界面

  1. 初始化Qt GUI应用程序框架
  2. 创建QML引擎用于界面渲染
  3. 设置QML主界面文件路径(使用Qt资源系统)
  4. 添加对象创建失败的异常处理
  5. 异步加载QML界面文件

自带的main.qml

显示一个窗口标题为“hello word”的空白页面

二、增加一个登录页面LoginWindow

以上操作完成之后,在qtcreator中可以看到多出了一个内容为空白的LoginWindow.qml文件

这里提供一个登录页面的代码

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12Window {id: loginWindowwidth: 300height: 200title: "用户登录"modality: Qt.ApplicationModalflags: Qt.DialogColumn {anchors.centerIn: parentspacing: 15width: parent.width * 0.8TextField {id: usernamewidth: parent.widthplaceholderText: "用户名"}TextField {id: passwordwidth: parent.widthplaceholderText: "密码"echoMode: TextInput.Password}Row {spacing: 10anchors.horizontalCenter: parent.horizontalCenterButton {text: "登录"onClicked: {if(username.text === "admin" && password.text === "123456") {console.log("登录成功")loginWindow.close()//关闭自己的窗口} else {console.log("登录失败")}}}Button {text: "退出"onClicked: {//退出方式一:强制关闭所有窗口,资源完全释放Qt.quit()//强制终止整个Qt应用程序进程//退出方式二:关闭两个窗口,资源有可能未完全释放//loginWindow.close()//关闭自己的窗口//mainWindow.close()//关闭主窗口}}}}
}

注意了,这里有一个坑,如果在刚创建项目时,你点击过运行项目。然后再添加LoginWindow.qml文件的话,会报以下错误:

qmlcache_loader.cpp:-1: error: undefined reference to `QmlCacheGeneratedCode::_0x5f__login_qml::qmlData'

这是qml的资源缓存没有包含新增加的login.qml导致,点击【构建】->【重新构建项目】之后,再点击运行项目就正常了(这个现象,你可以理解为,当你只修改.h头文件时,执行make,make会反馈“没有任何变化”,清掉缓存,重新编译就正常了)。

三、main.qml加载登录页面LoginWindow

注意一点,以上增加LoginWindow.qml文件时,它与main.qml是在同一个目录下,方便引用,以下提供两种引用方式:

方式一:静态加载

import QtQuick 2.12
import QtQuick.Window 2.12Window {id:mainWindowwidth: 640height: 480visible: truetitle: qsTr("Hello World")//在窗口完成初始化后执行Component.onCompleted: {loginwin.visible = true}//登录窗口LoginWindow{//文件名称:直接引用组件(静态加载)id:loginwinvisible: false}
}

方式二:动态加载

import QtQuick 2.12
import QtQuick.Window 2.12Window {id:mainWindowwidth: 640height: 480visible: truetitle: qsTr("Hello World")//在窗口完成初始化后执行Component.onCompleted: {var component = Qt.createComponent("LoginWindow.qml")if (component.status === Component.Ready) {var loginWindow = component.createObject(mainWindow)loginWindow.show()}}
}

场景

推荐方式

始终显示的界面元素

静态加载

按需加载的页面

动态加载

资源密集型组件

动态加载

简单的子组件

静态加载

需要频繁切换的视图

动态加载

应用核心组件

静态加载

四、登录页面在后端实时验证信息

在【三、main.qml加载登录页面LoginWindow】中提供了在qml上静态方式校验用户名和密码的代码,这只是为了让【三】能正常编译,实际项目中,是要动态方式校验的,以下展示创建一个后端的CheckPwd类进行校验,并于页面互通。

1、创建新类

添加过程跟QT项目一样,

2、声明及定义页面调用的函数

创建完成之后,在头文件checkpwd.h中加入页面引入的函数,代码如下

#ifndef CHECKPWD_H
#define CHECKPWD_H#include <QObject>
#include <QVariant>  //新增头文件,前后端传参/结果class CheckPwd : public QObject
{Q_OBJECT
public:explicit CheckPwd(QObject *parent = nullptr);//声明给qml调用的函数Q_INVOKABLE bool logincheck(const QVariant usrname,const QVariant passwd);signals:};#endif // CHECKPWD_H

要点有两个:

  1. 使用Q_INVOKABLE宏声明为qml调用的函数;
  2. 使用QVariant传参或者返回结果给qml,QVariant是Qt框架中提供的通用数据类型容器。QVariant的作用是:MVD(Model-View-‌Delegate)模式中Model<->Delegate之间传递数据的容器载体。‌

==============以下是关系图,内容来源于AI=====================

以下函数的定义代码,把QVariant转换成QString之后,其他就是常规的QT代码开发(以下代码只做简单的判断逻辑)

bool CheckPwd::logincheck(const QVariant usrname,const QVariant passwd){QString name=usrname.toString();QString pwd=passwd.toString();if(name== "admin" && pwd == "123456")return true;elsereturn false;
}

3、将C++类注册到QML系统

main.cpp中创建QML引擎并指定加载的qml页面之后才能显示该页面。qml页面要使用后端的C++类,也要进行注册,代码如下

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "checkpwd.h"  //-------------新增的头文件int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);//创建Qt GUI应用程序实例,管理主事件循环和应用程序资源QQmlApplicationEngine engine;//创建QML引擎,用于加载和运行QML界面文件const QUrl url(QStringLiteral("qrc:/main.qml"));//定义QML主界面文件的路径(qrc资源系统中的main.qml)QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,//连接引擎的objectCreated信号&app, [url](QObject *obj, const QUrl &objUrl) {if (!obj && url == objUrl)QCoreApplication::exit(-1);}, Qt::QueuedConnection); //使用队列连接确保异步执行//将C++类注册到QML系统//CheckPwd的类的名称,必须与checkpwd.h类中的名称完全一致//CheckPwdObj是自主命名(名称随意),在LoginWindow.qml页面中引用//PasswordValidator引用的类型名称qmlRegisterType<CheckPwd>("CheckPwdObj",1,0,"PasswordValidator");//-------新增的注册类//加载以上指定的main.qml文件engine.load(url);return app.exec();
}

4、qml引入C++类的函数

在LoginWindow.qml中增加3个要素:

  1. 头部通过import进行引用:import CheckPwdObj 1.0,对应关系如下
  2. 类型引用
        PasswordValidator {id: validator}
  3. C++函数引用
    Button {text: "登录"onClicked: {var pwdck = validator.logincheck(username.text,password.text);if(pwdck===true){console.log("登录成功")loginWindow.close()//关闭自己的窗口} else {console.log("登录失败")}}}

    完成以上3步骤即可实现引用C++类函数,LoginWindow.qml完整代码如下

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12import CheckPwdObj 1.0
Window {id: loginWindowwidth: 300height: 200title: "用户登录"modality: Qt.ApplicationModalflags: Qt.DialogPasswordValidator {id: validator}Column {anchors.centerIn: parentspacing: 15width: parent.width * 0.8TextField {id: usernamewidth: parent.widthplaceholderText: "用户名"}TextField {id: passwordwidth: parent.widthplaceholderText: "密码"echoMode: TextInput.Password}Row {spacing: 10anchors.horizontalCenter: parent.horizontalCenterButton {text: "登录"onClicked: {var pwdck = validator.logincheck(username.text,password.text);if(pwdck===true){console.log("登录成功")loginWindow.close()//关闭自己的窗口} else {console.log("登录失败")}/*if(username.text === "admin" && password.text === "123456") {console.log("登录成功")loginWindow.close()//关闭自己的窗口} else {console.log("登录失败")}*/}}Button {text: "退出"onClicked: {//退出方式一:强制关闭所有窗口,资源完全释放Qt.quit()//强制终止整个Qt应用程序进程//退出方式二:关闭两个窗口,资源有可能未完全释放//loginWindow.close()//关闭自己的窗口//mainWindow.close()//关闭主窗口}}}}
}

文章转载自:

http://endLDXhI.nwfpL.cn
http://ua3ll9Yg.nwfpL.cn
http://9UEdOlPz.nwfpL.cn
http://y9MgS0df.nwfpL.cn
http://ckG3cbOI.nwfpL.cn
http://A3O2uLzI.nwfpL.cn
http://CVcowfhW.nwfpL.cn
http://qknkPYwR.nwfpL.cn
http://sdQuBmje.nwfpL.cn
http://JdkF7uEo.nwfpL.cn
http://jvfj3ntE.nwfpL.cn
http://1WutWYm8.nwfpL.cn
http://sSGFFgwf.nwfpL.cn
http://tt6G3abL.nwfpL.cn
http://Ghp89WEV.nwfpL.cn
http://OsG9x6yR.nwfpL.cn
http://Lwr7CZdX.nwfpL.cn
http://EdDtwVdK.nwfpL.cn
http://KIphFfoz.nwfpL.cn
http://Dke2bUDz.nwfpL.cn
http://maeS4TPi.nwfpL.cn
http://hzAzBHn0.nwfpL.cn
http://vNj9phWt.nwfpL.cn
http://wpHdYHGf.nwfpL.cn
http://rpSwtu39.nwfpL.cn
http://9Nvl1Cao.nwfpL.cn
http://oMgKrDRC.nwfpL.cn
http://mIF15p8p.nwfpL.cn
http://l0b130X6.nwfpL.cn
http://mzYLMxs8.nwfpL.cn
http://www.dtcms.com/a/380089.html

相关文章:

  • 通义灵码产品演示: 数据库设计与数据分析
  • 大疆图传十公里原理:无人机图传技术解析
  • 【论文阅读】小模型是智能体的未来
  • 空间智能 × 无人机丨考拉悠然携 AI+应急创新产品亮相东盟博览会
  • 【C++】list容器的模拟实现
  • Java学习之——“IO流“的进阶流之打印流的学习
  • Vue 进阶实战:从待办清单到完整应用(路由 / 状态管理 / 性能优化全攻略)
  • 《用 Python 和 TensorFlow 构建你的第一个神经网络:从零开始识别手写数字》
  • 深入探索Vue.js:响应式原理与性能优化
  • 58.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--新增功能--图形验证码
  • 【Linux】基本指令 · 下
  • springboot+python+uniapp基于微信小程序的旅游服务系统景点信息展示 路线推荐 在线预约 评论互动系统
  • WebApp 的价值与实现:从浏览器架构到用户体验优化
  • 用户体验五大要点:从问题到解决方案的完整指南
  • 从ChatGPT家长控制功能看AI合规与技术应对策略
  • DeepSeek-VL 解析:混合视觉-语言模型如何超越传统计算机视觉方法
  • 从15kHz 到20MHz:为什么LTE带宽不能被子载波间隔整除?
  • Android SystemServer 系列专题【篇五:UserController用户状态控制】
  • Nature | 本周最新文献速递
  • Vuetify:构建优雅Vue应用的Material Design组件库
  • 6种A2A(智能体到智能体)的协议方案
  • 性能测试工具jmeter使用
  • [Windows] PDF 专业压缩工具 v3.0
  • kubectl常用命令
  • MinIO 分布式模式与纠删码
  • linux 宏 DEVICE_ATTR
  • 代码随想录刷题Day56
  • Ansible的 Playbook 模式详解
  • Qt 调用setLayout后,父对象自动设置
  • 现在中国香港服务器速度怎么样?