QML实现登陆功能,并记住用户登陆历史

该文描述了一个用C++编写的QLoginNameListModel类,该类用于存储和管理用户登录历史。模型与Qt的Popup和ListView组件结合,提供记住用户名、获取上次登录用户名和用户列表计数的功能。代码实现了从文本文件读取和写入登录信息,并在主窗口中展示登录历史。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

登陆demo效果如图:

用户登陆历史使用Popup+ListView组件,model采用c++model实现。

qloginnamelistmodel.h

#ifndef QLOGINNAMELISTMODEL_H
#define QLOGINNAMELISTMODEL_H

#include <QAbstractListModel>

class QLoginNameListModel : public QAbstractListModel
{
    Q_OBJECT

public:
    enum LoginNameRole {
        ul_role_name
    };

    Q_ENUM(LoginNameRole)

    explicit QLoginNameListModel(QObject *parent = nullptr);

    // Basic functionality:
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;

    //记住用户名
    Q_INVOKABLE int rememberLoginName(QString qsName);

    //上次登录的用户名
    Q_INVOKABLE QVariant lastLoginName();

    //获取记录的条数
    Q_INVOKABLE uint userListCount();
private:

    //同步数据
    int synchroData();
    QList<QStringList> m_data;
};

#endif // QLOGINNAMELISTMODEL_H

qloginnamelistmodel.cpp

#include "qloginnamelistmodel.h"
#include <QFile>
#include <QCoreApplication>
#include <QDebug>
#include <QSet>

QLoginNameListModel::QLoginNameListModel(QObject *parent)
    : QAbstractListModel(parent)
{
    synchroData();
}

int QLoginNameListModel::rowCount(const QModelIndex &parent) const
{
    // For list models only the root node (an invalid parent) should return the list's size. For all
    // other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
    if (parent.isValid())
        return 0;

    // FIXME: Implement me!
    return m_data.count();
}

QVariant QLoginNameListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() >= rowCount())
    {
        return "";
    }

    switch (role) {
    case LoginNameRole::ul_role_name:
        return m_data.at(index.row()).at(0);
        break;
    default:
        break;
    }
    return QVariant();
}

QHash<int, QByteArray> QLoginNameListModel::roleNames() const
{
    static const QHash<int, QByteArray> roles{
        { ul_role_name, "ul_role_name"},
    };
    return roles;
}

int QLoginNameListModel::synchroData()
{
    //从文件读取登录用户名
    QFile file(QCoreApplication::applicationDirPath() + "/logininfo.txt");
    bool isOk = file.open(QIODevice::ReadOnly | QIODevice::Text);        //以读写方式打开
    if (isOk)
    {
        beginResetModel();
        m_data.clear();
        //这里使用一行一行的读
        QStringList strNamenInfo;
        QTextStream in(&file);        //QFile中保留了换行符'\n';QTextStream中去掉了换行符'\n'
        while (!in.atEnd())
        {
            strNamenInfo.clear();
            //读一行
            strNamenInfo << in.readLine();
            if (!strNamenInfo.isEmpty())
            {
                m_data.append(strNamenInfo);
            }
        }
        endResetModel();
    }
    file.close();
    return 0;
}

int QLoginNameListModel::rememberLoginName(QString qsName)
{
    //按顺序读取文件中记录的所有用户名
    //在首位插入用户名
    //取前10个用户名,如果小于等于10个全部取出,按顺序重新写入文件
    QList<QStringList> dataList;
    QStringList nameInfo;
    nameInfo << qsName;
    dataList.append(nameInfo);
    //QList<QString> uniqueDataList = m_data.toSet().toList();          //用户名去重(注意这个会对数据重新按字典序排序)
    QList<QStringList> uniqueDataList = m_data;
    QList<QStringList>::iterator iter = uniqueDataList.begin();
    for (; iter != uniqueDataList.end();)
    {
        if (dataList.size() >= 10)
            break;
        if (qsName == (*iter).at(0))
        {
            //用户名已经存在,则删除之前的用户名,重新插入,保证每次默认显示的都是最新登录成功的
            iter = uniqueDataList.erase(iter);
        }
        else
        {
            dataList.append(*iter);
            ++iter;
        }

    }

    QFile file(QCoreApplication::applicationDirPath() + "/logininfo.txt");
    bool isOk = file.open(QIODevice::WriteOnly | QIODevice::Text | QFile::Truncate);        //以清空的方式打开
    if (isOk)
    {
        QTextStream out(&file);
        int i = 0;
        foreach(QStringList qsNameInfo, dataList)
        {
            if (i >= 10)
                break;
            foreach (QString nameItem, qsNameInfo) {
                out << nameItem;
            }
            out << endl;
            ++i;
        }
    }
    file.flush();
    file.close();
    synchroData();        //更新model数据
    return 0;
}

QVariant QLoginNameListModel::lastLoginName()
{
    if (m_data.size())
    {
        return m_data[0].at(0);
    }
    else
    {
        return "";
    }
}

uint QLoginNameListModel::userListCount()
{
    return m_data.size();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import LoginNameListModel 1.0

Window {
    id: appWin
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    property string loginerrreason: ""
    signal loginSignal(var uname, var password)

    //用户历史
    LoginNameListModel {
        id: loginusername
    }

    Component {
        id: login
        Login{
            anchors.fill: parent
        }
    }

    Component {
        id: appPage
        AppPannel{
            anchors.fill: parent
        }
    }

    Loader {
        id: pageloder
        anchors.fill: parent
        sourceComponent: login
    }

    function loginFunc(uname, password){
        if(("admin" === uname || "test" === uname)
                && "123456" === password){
            pageloder.sourceComponent = appPage
            //记住用户名
            loginusername.rememberLoginName(uname)
        }else{
            loginerrreason = qsTr("用户名密码错误!")
        }
    }

    function logoutFunc(){
        pageloder.sourceComponent = login
    }
}
import QtQuick 2.12
import QtQuick.Controls 2.12

Rectangle {
    anchors.fill: parent

    Button {
        text: qsTr("注销")
        anchors.right: parent.right
        onClicked: {
            appWin.logoutFunc()
        }
    }

    Text {
        id: name
        text: qsTr("Welcome LoginDemo!")
        anchors.centerIn: parent
        font.pixelSize: 14
    }
}

Login.qml

import QtQuick 2.12
import QtQuick.Controls 2.12

Rectangle {
    id: login
    anchors.fill: parent

    Column {
        spacing: 20
        anchors.centerIn: parent
        Row{
            id: t
            spacing: 10
            Column {
                spacing: 20
                Text {
                    text: qsTr("用户名")
                    height: 40
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignHCenter
                }

                Text {
                    text: qsTr("密码")
                    height: 40
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignHCenter
                }
            }

            Column {
                spacing: 20
                TextField {
                    id: name
                    height: 40
                    selectByMouse: true
                    placeholderText: qsTr("请输入用户名")
                    text: loginusrlist.selectName
                    onPressed: {
                        loginusrlist.x = name.mapToItem(login, 0, 0).x
                        loginusrlist.y = name.mapToItem(login, 0, 0).y+name.height+1
                        loginusrlist.open()
                    }

                }
                TextField {
                    id: pwd
                    height: 40
                    selectByMouse: true
                    placeholderText: qsTr("请输入密码")
                }
            }
        }

        Text {
            id: errCode
            color: "red"
            text: appWin.loginerrreason
            height: 20
        }

        Button {
            text: qsTr("登 陆")
            height: 40
            width: t.width
            onClicked: {
                appWin.loginerrreason = ""
                console.log("login: name=", name.text, "; pwd=", pwd.text)
                appWin.loginFunc(name.text, pwd.text)
            }
        }
    }

    LoginUserList {
        id: loginusrlist
    }
}

LoginUserList.qml

import QtQuick 2.12
import QtQuick.Controls 2.12

Popup {
    id: ulItem
    height: loginusername.userListCount()*40
    width: 240

    property string selectName: ""

    background: ListView {
        anchors.fill: parent
        model: loginusername
        clip: true //对超出划定边界的数据进行裁剪
        delegate: Rectangle {
            id: userItem
            color: "lightblue"
            width: ulItem.width
            height: nameTxt.text === "" ? 0: 40

            Text {
                id: nameTxt
                x: 11
                anchors.verticalCenter: parent.verticalCenter
                text: ul_role_name
            }

            Rectangle {
                width: ulItem.width
                height: 1
                color: "gray"
            }

            MouseArea {
                anchors.fill: parent
                hoverEnabled: true

                onContainsMouseChanged: {
                    if(containsMouse) {
                        parent.color = "lightgreen"
                    }else{
                        parent.color = "lightblue"
                    }
                }

                onClicked: {
                    ulItem.selectName = ul_role_name
                    ulItem.visible = false
                }
            }
        }
    }
}

main.qml

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <qqml.h>
#include "qloginnamelistmodel.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    qmlRegisterType<QLoginNameListModel>(
                "LoginNameListModel",
                1, 0,
                "LoginNameListModel");

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_君莫笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值