├── README.md ├── resource ├── 008 Rainy Ashville.png ├── 050 Snow Again.png ├── 051 February Ink.png ├── 094 Cloudy Apple - trans.png ├── 094 Cloudy Apple.png ├── addfriends.jpg ├── andan.jpg ├── andan_touming.jpg ├── back.png ├── suliao.png ├── suliao_avator.png ├── suliao_avator_normal.jpg ├── suliao_big.png ├── suliao_normal.png └── tubiao.qrc ├── server └── server │ ├── clienthandler.cpp │ ├── clienthandler.h │ ├── connectionpool.cpp │ ├── connectionpool.h │ ├── main.cpp │ ├── server.cpp │ ├── server.h │ ├── server.pro │ ├── server.pro.user │ ├── server.ui │ └── server_zh_CN.ts └── user └── user ├── addfriends.cpp ├── addfriends.h ├── addfriends.ui ├── autocleartextedit.cpp ├── autocleartextedit.h ├── changeinformation.cpp ├── changeinformation.h ├── changeinformation.ui ├── changepassword.cpp ├── changepassword.h ├── changepassword.ui ├── choicedialog.cpp ├── choicedialog.h ├── choicedialog.ui ├── cutavator.cpp ├── cutavator.h ├── cutavator.ui ├── dialog.cpp ├── dialog.h ├── dialog.ui ├── findpassword.cpp ├── findpassword.h ├── findpassword.ui ├── friendmessage.cpp ├── friendmessage.h ├── friendmessage.ui ├── login.cpp ├── login.h ├── login.ui ├── logout.cpp ├── logout.h ├── logout.ui ├── main.cpp ├── mainwindow-else.cpp ├── mainwindow-else.h ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── registerwindow.cpp ├── registerwindow.h ├── registerwindow.ui ├── user.pro ├── user.pro.user └── user_zh_CN.ts /README.md: -------------------------------------------------------------------------------- 1 | 这是博主学习几个月后做的第一个项目 qt版本是6.7.2 之前没有开发经验 所以可能bug会比较多 我也会持续修改更新 代码也比较杂乱 好在注释加的比较多 2 | 大家有需要的可以重构一下 大家把login和mainwindow的tcpConnect函数的地址和端口号改为自己需要的就可以使用了 3 | 因为qt6没有自带mysql的驱动 所以数据库直接使用的sqlite 数据库代码也可以在文件中找到 4 | -------------------------------------------------------------------------------- /resource/008 Rainy Ashville.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/008 Rainy Ashville.png -------------------------------------------------------------------------------- /resource/050 Snow Again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/050 Snow Again.png -------------------------------------------------------------------------------- /resource/051 February Ink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/051 February Ink.png -------------------------------------------------------------------------------- /resource/094 Cloudy Apple - trans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/094 Cloudy Apple - trans.png -------------------------------------------------------------------------------- /resource/094 Cloudy Apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/094 Cloudy Apple.png -------------------------------------------------------------------------------- /resource/addfriends.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/addfriends.jpg -------------------------------------------------------------------------------- /resource/andan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/andan.jpg -------------------------------------------------------------------------------- /resource/andan_touming.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/andan_touming.jpg -------------------------------------------------------------------------------- /resource/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/back.png -------------------------------------------------------------------------------- /resource/suliao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/suliao.png -------------------------------------------------------------------------------- /resource/suliao_avator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/suliao_avator.png -------------------------------------------------------------------------------- /resource/suliao_avator_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/suliao_avator_normal.jpg -------------------------------------------------------------------------------- /resource/suliao_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/suliao_big.png -------------------------------------------------------------------------------- /resource/suliao_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qiuyue0125/SULIAO/11f937e6d174f11f1528a3996052df3c8e522550/resource/suliao_normal.png -------------------------------------------------------------------------------- /resource/tubiao.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | suliao.png 4 | suliao_avator.png 5 | suliao_avator_normal.jpg 6 | 008 Rainy Ashville.png 7 | 051 February Ink.png 8 | 050 Snow Again.png 9 | 094 Cloudy Apple.png 10 | addfriends.jpg 11 | andan.jpg 12 | andan_touming.jpg 13 | 094 Cloudy Apple - trans.png 14 | back.png 15 | 16 | 17 | -------------------------------------------------------------------------------- /server/server/clienthandler.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIENTHANDLER_H 2 | #define CLIENTHANDLER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "server.h" 26 | #include "connectionpool.h" 27 | 28 | class Server; 29 | 30 | class ClientHandler : public QThread//用来处理消息的类 31 | { 32 | Q_OBJECT 33 | public: 34 | ClientHandler(QTcpSocket *socket,ConnectionPool& pool,Server *srv); 35 | ~ClientHandler(); 36 | void run() override;//启用事件循环 37 | bool databasesConnect();//连接数据库 38 | void addClient(const QString &account, ClientHandler *client);//将登录成功的用户增加到哈希存储 39 | void removeClient(const QString &account);//用户断开连接 删除对应的哈希存储 40 | ClientHandler* getClient(const QString &account);//获得某个账号对应的ClientHandler 41 | 42 | public slots: 43 | void onReadyRead();//读取用户发送的数据 44 | void onDisconnected();//有用户断联了 45 | void receiveMessage(const QJsonObject &json);//收到别的客户端发送的消息 然后转发 46 | 47 | public://接收到客户端发送的消息 然后回发 48 | QString pixmapToBase64(const QPixmap &pixmap);//图片转换成base64格式 49 | QPixmap base64ToPixmap(const QString &base64Str);//将base64转换为图片 50 | void dealLogin(const QJsonObject &json);//处理登录请求 51 | void dealRegister(const QJsonObject &json);//处理注册请求 52 | void dealAvator(const QString &avator);//上传头像 53 | void dealAskforavator(const QString &qqnum);//处理索要头像的请求 54 | void dealFindpassword1(const QString &qqnum);//看看找回的密码是不是有这个账号 55 | void dealFindpassword2(const QJsonObject &json);//查看密保问题回答对了没有 json和全局变量jsonobj一样 56 | void dealFindpassword3(const QJsonObject &json);//修改密码 json和全局变量jsonobj一样 57 | void dealLoginFirst(const QJsonObject &json);//处理用户登录成功后初始化 58 | void dealDeleteFriend(const QJsonObject &json);//处理删除好友的操作 59 | void dealSerachAccount(const QJsonObject &json);//处理用户搜索账户信息的功能 60 | void dealChangeInformation(const QJsonObject &json);//处理用户更新个人信息的功能 61 | void dealChangePassword(const QJsonObject &json);//处理用户更新密码的功能 62 | void dealChangePassword2(const QJsonObject &json);//处理用户更新密码的功能 63 | void dealLogout(const QJsonObject &json);//处理用户注销的功能 64 | void dealAddFriends(const QJsonObject &json);//处理用发送户添加好友申请的功能 65 | void dealAddNewFriends(const QJsonObject &json);//处理用户回应是否添加好友的功能 66 | void dealMessages(const QJsonObject json);//处理用户发送的消息 67 | void sendNextMessage();//从队列发送下一条消息(处理文件) 68 | void dealAskDocument(const QJsonObject &json);//处理用户要下载文件的要求 69 | 70 | public://接收到别的服务器发送的消息 然后转发 71 | void forwordAddFriendRequest(const QJsonObject &json);//向在线用户转发用户好友申请 72 | void forwordRequestPass(const QJsonObject &json);//向在线用户更新他的好友列表(他的好友申请被通过) 73 | void forwordYouAreDeleted(const QJsonObject &json);//向在线用户更新他的好友列表(他被删除了) 74 | void forwordKickedOffline(const QJsonObject &json);//把在线用户挤下线 75 | void forwordMessages(const QJsonObject &json);//向在线用户发送聊天消息 76 | 77 | signals: 78 | void sendMessage(const QJsonObject &json);//给别的客户端发送消息 79 | 80 | private: 81 | static QMutex dbMutex; 82 | static QReadWriteLock lock; 83 | QMutex mutex; 84 | ConnectionPool& pool; 85 | QSqlDatabase db; 86 | QTcpSocket *socket; 87 | QJsonDocument jsonDoc; 88 | QJsonObject jsonObj; 89 | QByteArray jsonData; 90 | QByteArray bufferedData; 91 | Server *srv;//指向服务器的指针 92 | QString randomNumber;//注册随机生成账号 93 | QString account = "0";//登录成功存储账号 94 | QQueue messageQueue; //用于存储待发送的消息 95 | bool isSending = false; //用于标记消息是否正在发送 96 | int flag = 0; 97 | }; 98 | 99 | 100 | class DocumentWorker : public QObject//负责查询的类 101 | { 102 | Q_OBJECT 103 | public: 104 | DocumentWorker(const QString &filename, const QString ×tamp, QSqlDatabase db) 105 | : filename(filename), timestamp(timestamp), db(db) {} 106 | 107 | signals: 108 | void resultReady(const QJsonObject &result); 109 | 110 | public slots: 111 | void process();//处理查询文件 112 | 113 | private: 114 | QString filename; 115 | QString timestamp; 116 | QSqlDatabase db; 117 | }; 118 | 119 | 120 | 121 | #endif // CLIENTHANDLER_H 122 | -------------------------------------------------------------------------------- /server/server/connectionpool.cpp: -------------------------------------------------------------------------------- 1 | #include "connectionpool.h" 2 | 3 | ConnectionPool& ConnectionPool::getInstance()//获取单例实例 4 | { 5 | static ConnectionPool instance;//确保是同一个实例 6 | return instance; 7 | } 8 | 9 | 10 | QSqlDatabase ConnectionPool::getConnection() // 获取数据库连接 11 | { 12 | QMutexLocker locker(&mutex); 13 | if (!pool.isEmpty()) { 14 | QSqlDatabase db = pool.dequeue(); 15 | if (db.isOpen()) { 16 | qDebug() << "有现成的连接"; 17 | return db; 18 | } else { 19 | db.close(); 20 | qDebug() << "连接已关闭,丢弃该连接,尝试创建新连接..."; 21 | return getConnection(); 22 | } 23 | } 24 | //如果没有可用的连接且池未满,则新建连接 25 | if (pool.size() < maxConnections) { 26 | QString connectionName = QString("Connection_%1").arg(connectionCounter++); 27 | QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName); 28 | db.setDatabaseName(dbName); 29 | if (!db.open()) { 30 | qDebug() << "数据库打开失败:" << db.lastError().text(); 31 | return QSqlDatabase(); 32 | } 33 | return db; // 返回新连接 34 | } else { 35 | qDebug() << "数据库最大连接数已达到!"; 36 | return QSqlDatabase(); 37 | } 38 | } 39 | 40 | 41 | void ConnectionPool::releaseConnection(QSqlDatabase db)//释放连接 42 | { 43 | QMutexLocker locker(&mutex); 44 | if (pool.size() < maxConnections) { 45 | pool.enqueue(db); 46 | } else { 47 | db.close(); 48 | } 49 | } 50 | 51 | 52 | void ConnectionPool::setMaxConnections(int max)//设置最大连接数 53 | { 54 | QMutexLocker locker(&mutex); 55 | maxConnections = max; 56 | } 57 | 58 | 59 | int ConnectionPool::getMaxConnections() const//获取当前最大连接数 60 | { 61 | return maxConnections; 62 | } 63 | 64 | 65 | ConnectionPool::ConnectionPool() : maxConnections(301)//私有构造函数 默认最大连接数 66 | { 67 | //建立数据库 68 | QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", dbName); 69 | db.setDatabaseName(dbName); 70 | if (!db.open()) { 71 | qDebug() << "打开数据库失败" << db.lastError().text(); 72 | } 73 | else{ 74 | //检查和创建表的 SQL 语句 75 | QSqlQuery query(db); 76 | //创建用户表 77 | query.exec("CREATE TABLE IF NOT EXISTS Users (" 78 | "qq_number VARCHAR(20) PRIMARY KEY NOT NULL, " 79 | "password VARCHAR(255) NOT NULL, " 80 | "avator LONGTEXT, " 81 | "nickname VARCHAR(50), " 82 | "signature TEXT, " 83 | "gender TEXT CHECK (gender IN ('男', '女', '其他')), " 84 | "question VARCHAR(255), " 85 | "answer VARCHAR(255));"); 86 | if (query.lastError().isValid()) { 87 | qDebug() << "创建用户表失败:" << query.lastError().text(); 88 | } 89 | //创建聊天消息表 90 | query.exec("CREATE TABLE IF NOT EXISTS Messages (" 91 | "message_id INTEGER PRIMARY KEY AUTOINCREMENT, " 92 | "sender_id VARCHAR(20) NOT NULL, " 93 | "receiver_id VARCHAR(20) NOT NULL, " 94 | "content LONGTEXT, " 95 | "filename VARCHAT(20)," 96 | "status VARCHAT(20)," 97 | "timestamp TIMESTAMP, " 98 | "message_type VARCHAR(20) NOT NULL, " 99 | "FOREIGN KEY (sender_id) REFERENCES Users(qq_number) ON DELETE CASCADE);"); 100 | if (query.lastError().isValid()) { 101 | qDebug() << "创建聊天消息表失败:" << query.lastError().text(); 102 | } 103 | //创建好友关系表 104 | query.exec("CREATE TABLE IF NOT EXISTS Friends (" 105 | "friendship_id INTEGER PRIMARY KEY AUTOINCREMENT, " 106 | "user_id VARCHAR(20) NOT NULL, " 107 | "friend_id VARCHAR(20) NOT NULL, " 108 | "FOREIGN KEY (user_id) REFERENCES Users(qq_number) ON DELETE CASCADE, " 109 | "FOREIGN KEY (friend_id) REFERENCES Users(qq_number) ON DELETE CASCADE);"); 110 | if (query.lastError().isValid()) { 111 | qDebug() << "创建好友关系表失败:" << query.lastError().text(); 112 | } 113 | //创建申请表 114 | query.exec("CREATE TABLE IF NOT EXISTS FriendRequests (" 115 | "request_id INTEGER PRIMARY KEY AUTOINCREMENT, " 116 | "sender_id VARCHAR(20) NOT NULL, " 117 | "receiver_id INT NOT NULL, " 118 | "request_type TEXT CHECK (request_type IN ('friend', 'group')) NOT NULL, " 119 | "status TEXT CHECK (status IN ('pending', 'accepted', 'rejected')) NOT NULL DEFAULT 'pending', " 120 | "timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " 121 | "FOREIGN KEY (sender_id) REFERENCES Users(qq_number) ON DELETE CASCADE);"); 122 | if (query.lastError().isValid()) { 123 | qDebug() << "创建申请表失败:" << query.lastError().text(); 124 | } 125 | db.close(); 126 | } 127 | } 128 | 129 | 130 | ConnectionPool::~ConnectionPool()//私有析构函数 131 | { 132 | while (!pool.isEmpty()) { 133 | QSqlDatabase db = pool.dequeue(); 134 | db.close();//关闭所有连接 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /server/server/connectionpool.h: -------------------------------------------------------------------------------- 1 | #ifndef CONNECTIONPOOL_H 2 | #define CONNECTIONPOOL_H 3 | 4 | #include "qmutex.h" 5 | #include "qsqldatabase.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | class ConnectionPool {//连接池 17 | public: 18 | static ConnectionPool& getInstance();//获取单例实例 19 | QSqlDatabase getConnection();//获取数据库连接 20 | void releaseConnection(QSqlDatabase db);//释放连接 21 | void setMaxConnections(int max);//设置最大连接数 22 | int getMaxConnections() const;//获取当前最大连接数 23 | 24 | private: 25 | ConnectionPool();//私有构造函数 26 | ~ConnectionPool();//私有析构函数 27 | QQueue pool;//连接池 28 | QMutex mutex;//互斥锁 29 | int maxConnections;//最大连接数 30 | QString dbName = "suliaoserver.db";//数据库名字 31 | int connectionCounter = 0;//连接个数 起名字 32 | }; 33 | 34 | #endif // CONNECTIONPOOL_H 35 | -------------------------------------------------------------------------------- /server/server/main.cpp: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | QApplication a(argc, argv); 11 | QTranslator translator; 12 | const QStringList uiLanguages = QLocale::system().uiLanguages(); 13 | for (const QString &locale : uiLanguages) { 14 | const QString baseName = "server_" + QLocale(locale).name(); 15 | if (translator.load(":/i18n/" + baseName)) { 16 | a.installTranslator(&translator); 17 | break; 18 | } 19 | } 20 | Server w; 21 | w.show(); 22 | return a.exec(); 23 | } 24 | -------------------------------------------------------------------------------- /server/server/server.cpp: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | #include "ui_server.h" 3 | #include "clienthandler.h" 4 | 5 | Server::Server(QWidget *parent) 6 | : QMainWindow(parent) 7 | , ui(new Ui::Server) 8 | { 9 | ui->setupUi(this); 10 | //连接数据库 11 | databasesConnect(); 12 | //显示表格 13 | showTable("Users"); 14 | ui->table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 15 | //初始化tcp对象 16 | TCP = new QTcpServer(this); 17 | } 18 | 19 | 20 | Server::~Server(){ 21 | delete ui; 22 | } 23 | 24 | 25 | bool Server::databasesConnect()//连接数据库 26 | { 27 | ConnectionPool& pool = ConnectionPool::getInstance();//获取连接池实例 28 | Server::db = pool.getConnection();//从连接池获取一个数据库连接 29 | if (!db.isValid()) {//检查连接是否有效 30 | qDebug() << "打开失败: 获取数据库连接失败"; 31 | return false;//连接获取失败 32 | } else { 33 | qDebug() << "数据库连接成功"; 34 | qry = QSqlQuery(db);//使用有效连接创建查询对象 35 | return true; 36 | } 37 | } 38 | 39 | 40 | void Server::showTable(const QString &tablename)//显示表格 41 | { 42 | QString queryStr; 43 | if (tablename == "Users") { 44 | queryStr = "SELECT qq_number,password,nickname,signature,gender,question,answer FROM Users"; 45 | } else if (tablename == "Messages") { 46 | queryStr = "SELECT sender_id,receiver_id,timestamp,message_type,filename,status FROM Messages"; 47 | } else if (tablename == "Friends") { 48 | queryStr = "SELECT * FROM Friends"; 49 | } else if (tablename == "FriendRequests") { 50 | queryStr = "SELECT * FROM FriendRequests"; 51 | } 52 | //创建模型并设置查询 53 | QSqlQueryModel *model = new QSqlQueryModel(this); 54 | model->setQuery(queryStr, Server::db); 55 | if (model->lastError().isValid()) { 56 | qDebug() << "查询失败:" << model->lastError().text(); 57 | return; 58 | } 59 | qDebug() << "加载行数:" << model->rowCount(); 60 | ui->table->setModel(model); 61 | } 62 | 63 | 64 | bool Server::tcpListen()//建立连接,监听对象 65 | { 66 | connect(TCP, &QTcpServer::newConnection, this, &Server::onNewConnection); 67 | if (!TCP->listen(QHostAddress::Any, 1999)) { 68 | qDebug() << "监听失败:" << TCP->errorString(); 69 | return false; 70 | } else { 71 | qDebug() << "监听成功"; 72 | return true; 73 | } 74 | } 75 | 76 | 77 | void Server::on_whichtable_currentIndexChanged(int index)//切换表格 78 | { 79 | if(index == 0) 80 | showTable("Users"); 81 | if(index == 1) 82 | showTable("Messages"); 83 | if(index == 2) 84 | showTable("Friends"); 85 | if(index == 3) 86 | showTable("FriendRequests"); 87 | } 88 | 89 | 90 | void Server::on_sqlsubmit_clicked()//提交执行SQL语句 91 | { 92 | if (qry.prepare(ui->sql->text()) && qry.exec()) { 93 | showTable(ui->whichtable->currentText()); 94 | } else { 95 | qDebug() << "SQL 执行错误:" << qry.lastError().text(); 96 | } 97 | } 98 | 99 | 100 | void Server::onNewConnection()//有新连接到来新建clienthandler 101 | { 102 | qDebug()<<"主线程是"<currentThreadId(); 103 | QTcpSocket *socket = TCP->nextPendingConnection(); 104 | ConnectionPool& pool = ConnectionPool::getInstance();//获取连接池实例 105 | ClientHandler* handler = new ClientHandler(socket, pool, this); 106 | handler->start(); 107 | } 108 | 109 | 110 | void Server::on_listen_clicked()//点击开启/关闭服务器 启动/关闭监听 111 | { 112 | if(!listenFlag) { 113 | ui->listen->setText("关闭服务器"); 114 | listenFlag = true; 115 | tcpListen();//直接调用当前对象的 tcpListen 方法 116 | } else { 117 | ui->listen->setText("开启服务器"); 118 | listenFlag = false; 119 | qDebug()<<"服务器关闭"; 120 | TCP->close();//确保关闭 TCP 服务器 121 | } 122 | } 123 | 124 | 125 | void Server::on_pushButton_clicked()//刷新表格 126 | { 127 | qDebug()<<"当前连接的账号有"<whichtable->currentIndex()); 129 | } 130 | 131 | 132 | -------------------------------------------------------------------------------- /server/server/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | class ClientHandler; 24 | 25 | QT_BEGIN_NAMESPACE 26 | namespace Ui { 27 | class Server; 28 | } 29 | QT_END_NAMESPACE 30 | 31 | 32 | class Server : public QMainWindow 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | explicit Server(QWidget *parent = nullptr); 38 | ~Server(); 39 | bool databasesConnect();//连接数据库 40 | void showTable(const QString &tablename);//显示表格 41 | bool tcpListen();//建立连接,监听对象 42 | 43 | private slots: 44 | void on_whichtable_currentIndexChanged(int index);//切换表格 45 | void on_sqlsubmit_clicked();//使用SQL语句 46 | void onNewConnection();//有新连接到来新建clienthandler 47 | void on_listen_clicked();//点击开启/关闭服务器 启动/关闭监听 48 | void on_pushButton_clicked();//刷新表格 49 | 50 | private: 51 | Ui::Server *ui; 52 | QThreadPool *threadPool;//线程池 53 | QMutex mapMutex; // 互斥量,确保线程安全 54 | QSqlDatabase db; 55 | QSqlQuery qry; 56 | QTcpServer *TCP; 57 | bool listenFlag = false; 58 | 59 | public: 60 | QHash clientsMap;//存储账号与ClientHandler的映射 共享资源 61 | }; 62 | 63 | #endif // SERVER_H 64 | -------------------------------------------------------------------------------- /server/server/server.pro: -------------------------------------------------------------------------------- 1 | QT += core gui \ 2 | quick 3 | QT += core gui sql 4 | QT += sql 5 | QT += core network 6 | 7 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 8 | 9 | CONFIG += c++17 10 | 11 | # You can make your code fail to compile if it uses deprecated APIs. 12 | # In order to do so, uncomment the following line. 13 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 14 | 15 | SOURCES += \ 16 | clienthandler.cpp \ 17 | connectionpool.cpp \ 18 | main.cpp \ 19 | server.cpp 20 | 21 | HEADERS += \ 22 | clienthandler.h \ 23 | connectionpool.h \ 24 | server.h 25 | 26 | FORMS += \ 27 | server.ui 28 | 29 | TRANSLATIONS += \ 30 | server_zh_CN.ts 31 | CONFIG += lrelease 32 | CONFIG += embed_translations 33 | 34 | # Default rules for deployment. 35 | qnx: target.path = /tmp/$${TARGET}/bin 36 | else: unix:!android: target.path = /opt/$${TARGET}/bin 37 | !isEmpty(target.path): INSTALLS += target 38 | -------------------------------------------------------------------------------- /server/server/server.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Server 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1100 10 | 600 11 | 12 | 13 | 14 | 15 | 1100 16 | 600 17 | 18 | 19 | 20 | 21 | 1100 22 | 600 23 | 24 | 25 | 26 | server 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 20 36 | 10 37 | 1061 38 | 561 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 49 | 50 50 | 51 | 52 | 53 | 54 | 150 55 | 32 56 | 57 | 58 | 59 | font: 10pt "Microsoft YaHei UI"; 60 | 61 | 62 | 63 | 64 | 65 | Users 66 | 67 | 68 | 69 | 70 | Messages 71 | 72 | 73 | 74 | 75 | Friends 76 | 77 | 78 | 79 | 80 | FriendRequests 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 0 90 | 9 91 | 92 | 93 | 94 | 95 | 80 96 | 27 97 | 98 | 99 | 100 | QPushButton{ 101 | font: 10pt "Microsoft YaHei UI"; 102 | border: 1px solid rgba(0, 0, 0, 0.3); 103 | } 104 | QPushButton:pressed { 105 | font: 10pt "Microsoft YaHei UI"; 106 | border: 1px solid rgba(0, 0, 0, 0.3); 107 | background-color: rgb(255, 251, 255); 108 | } 109 | 110 | 111 | 开启服务器 112 | 113 | 114 | false 115 | 116 | 117 | false 118 | 119 | 120 | false 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 0 129 | 10 130 | 131 | 132 | 133 | 134 | 80 135 | 27 136 | 137 | 138 | 139 | QPushButton{ 140 | font: 10pt "Microsoft YaHei UI"; 141 | border: 1px solid rgba(0, 0, 0, 0.3); 142 | } 143 | QPushButton:pressed { 144 | font: 10pt "Microsoft YaHei UI"; 145 | border: 1px solid rgba(0, 0, 0, 0.3); 146 | background-color: rgb(255, 251, 255); 147 | } 148 | 149 | 150 | 刷新表格 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 50 161 | 50 162 | 163 | 164 | 165 | font: 10pt "Microsoft YaHei UI"; 166 | border: 1px solid rgba(0, 0, 0, 0.3); 167 | 168 | 169 | 170 | false 171 | 172 | 173 | false 174 | 175 | 176 | false 177 | 178 | 179 | false 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 50 190 | 50 191 | 192 | 193 | 194 | font: 12pt "Microsoft YaHei UI"; 195 | border: 1px solid rgba(0, 0, 0, 0.3); 196 | 197 | 198 | 199 | 请输入SQL语句 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 5 208 | 50 209 | 210 | 211 | 212 | QPushButton{ 213 | font: 12pt "Microsoft YaHei UI"; 214 | border: 1px solid rgba(0, 0, 0, 0.3); 215 | } 216 | QPushButton:pressed { 217 | font: 12pt "Microsoft YaHei UI"; 218 | border: 1px solid rgba(0, 0, 0, 0.3); 219 | background-color: rgb(255, 251, 255); 220 | } 221 | 222 | 223 | 提交 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 0 236 | 0 237 | 1100 238 | 18 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | -------------------------------------------------------------------------------- /server/server/server_zh_CN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /user/user/addfriends.cpp: -------------------------------------------------------------------------------- 1 | #include "addfriends.h" 2 | #include "ui_addfriends.h" 3 | #include "autocleartextedit.h" 4 | #include "dialog.h" 5 | #include "choicedialog.h" 6 | 7 | AddFriends::AddFriends(QWidget *parent) 8 | : QDialog(parent) 9 | , ui(new Ui::AddFriends) 10 | { 11 | ui->setupUi(this); 12 | //初始化窗口 13 | QIcon icon(":/pictures/suliao.png"); 14 | setWindowIcon(icon); 15 | setWindowFlags( Qt::FramelessWindowHint | Qt::Dialog); 16 | setAttribute(Qt::WA_TranslucentBackground);//允许背景透明 17 | //清除输入框焦点 18 | ui->line_serach->clearFocus(); 19 | // 将窗口居中显示 20 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 21 | if (topLevelParent) { 22 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 23 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 24 | move(x, y); 25 | } 26 | } 27 | 28 | 29 | AddFriends::~AddFriends() 30 | { 31 | delete ui; 32 | //this->disconnect();放在主窗口的槽函数中了 33 | qDebug()<<"添加好友窗口析构函数执行"; 34 | } 35 | 36 | 37 | void AddFriends::paintEvent(QPaintEvent *event)//窗口背景 38 | { 39 | //调用基类方法以处理父类的绘图 40 | QDialog::paintEvent(event); 41 | QPainter painter(this); 42 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 43 | //加载背景图片 44 | QPixmap background(":/pictures/094 Cloudy Apple - trans.png"); 45 | //确保图片已加载 46 | if (background.isNull()) { 47 | qWarning("背景图像加载失败"); 48 | return; 49 | } 50 | QSize newSize = QSize(this->width(), this->height()); 51 | //将背景图缩放为新的大小 52 | QPixmap scaledBackground = background.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 53 | //计算绘制的位置,保持居中 54 | int x = (this->width() - scaledBackground.width()) / 2; 55 | int y = (this->height() - scaledBackground.height()) / 2; 56 | //设置剪裁区域以适应圆角窗口 57 | int radius = 10; 58 | QPainterPath path; 59 | path.addRoundedRect(rect(), radius, radius); 60 | painter.setClipPath(path); 61 | //绘制背景图片 62 | painter.drawPixmap(x, y, scaledBackground); 63 | //绘制边框 64 | painter.setPen(QPen(Qt::gray, 3.5)); 65 | painter.drawRoundedRect(rect(), radius, radius); 66 | } 67 | 68 | 69 | void AddFriends::mousePressEvent(QMouseEvent *event)//捕获鼠标按下事件 70 | { 71 | //清除焦点 72 | QList widgets = this->findChildren(); 73 | for (QWidget* widget : widgets) { 74 | widget->clearFocus(); 75 | } 76 | QPoint pos = event->pos(); 77 | int margin = 30; 78 | if (pos.x() <= 30 || pos.x() >= width() - 30 || 79 | pos.y() <= 30 || pos.y() >= height() - 30){//如果点击在边缘 80 | qDebug() << "点击在边缘"; 81 | moveFlag = 1; 82 | dragPosition = event->globalPosition().toPoint() - this->frameGeometry().topLeft();//记录鼠标相对于窗口的初始偏移 83 | event->accept(); 84 | } 85 | } 86 | 87 | 88 | void AddFriends::mouseMoveEvent(QMouseEvent *event)//实现拖拽移动效果与调整大小效果 89 | { 90 | qDebug()<<"鼠标位移了"; 91 | QPoint globalPos = event->globalPosition().toPoint();//获取当前的鼠标位置 92 | QPoint delta = globalPos - (this->frameGeometry().topLeft() + dragPosition);//计算当前鼠标位置与窗口之间的相对偏移 93 | if (event->buttons() & Qt::LeftButton) { 94 | if (moveFlag == 1) { 95 | this->move(globalPos - dragPosition); 96 | event->accept(); 97 | } 98 | //更新拖动位置 99 | dragPosition = globalPos - this->frameGeometry().topLeft(); 100 | } 101 | } 102 | 103 | 104 | void AddFriends::mouseReleaseEvent(QMouseEvent *event)//重置移动状态 105 | { 106 | moveFlag = 0; 107 | } 108 | 109 | 110 | void AddFriends:: closeEvent(QCloseEvent *event)//关闭窗口事件 111 | { 112 | emit customClose();//this->disconnect();放在主窗口的槽函数中了 113 | this->deleteLater(); 114 | event->accept(); 115 | } 116 | 117 | 118 | void AddFriends::on_but_deletewindow_clicked()//关闭窗口按钮 119 | { 120 | this->close(); 121 | } 122 | 123 | 124 | void AddFriends::on_line_serach_returnPressed()//搜索好友 125 | { 126 | if(ui->line_serach->text() == "输入对方账号搜索" || ui->line_serach->text().length() != 10){ 127 | QString text = "请输入正确的账号。"; 128 | Dialog* dialog = new Dialog(this); 129 | dialog->transText(text); 130 | dialog->exec(); 131 | return; 132 | } 133 | emit serachFriends(ui->line_serach->text()); 134 | ui->line_serach->clearFocus(); 135 | } 136 | 137 | 138 | void AddFriends::on_but_fangdajing_clicked()//点击放大镜也是搜索 139 | { 140 | on_line_serach_returnPressed(); 141 | } 142 | 143 | 144 | void AddFriends::serachResult(const QJsonObject &json)//查找账号的结果 145 | { 146 | if(json["answer"] == "fail"){ 147 | QString text = "没有找到用户,请检查您输入的账号。"; 148 | Dialog* dialog = new Dialog(this); 149 | dialog->transText(text); 150 | dialog->exec(); 151 | } 152 | else if(json["answer"] == "succeed"){ 153 | //删除旧控件 154 | QLayoutItem *item; 155 | while ((item = ui->layout_frame->takeAt(0)) != nullptr) { 156 | delete item->widget();//删除控件 157 | delete item;//删除布局项 158 | } 159 | //添加间隔器 160 | QSpacerItem *spacertop = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding); 161 | ui->layout_frame->addItem(spacertop); 162 | //添加信息标签 163 | auto addTextEditWithStyle = [&](const QString &prefix, const QString &text) { 164 | AutoClearTextEdit *textEdit = new AutoClearTextEdit(prefix + text); 165 | textEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); 166 | textEdit->setFixedSize(300, 42); 167 | textEdit->setStyleSheet( 168 | "font-size: 15px; " 169 | "color: #333333; " 170 | "font-weight: bold; " 171 | "padding: 5px; " 172 | "background: rgba(255, 255, 255 , 10); " 173 | "border: 1.5px solid black; " 174 | "border-radius: 5px;"); 175 | textEdit->setAlignment(Qt::AlignCenter); 176 | textEdit->setReadOnly(true);//设置为只读 177 | textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用垂直滚动条 178 | textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用水平滚动条 179 | return textEdit; 180 | }; 181 | //获取用户信息 182 | accountNum = json["account_num"].toString(); 183 | QString nickname = json["nickname"].toString(); 184 | QString gender = json["gender"].toString(); 185 | QString birthday = json["birthday"].toString(); 186 | QString signature = json["signature"].toString(); 187 | QString avator = json["avator"].toString();//base64 188 | QByteArray byteArray = QByteArray::fromBase64(avator.toUtf8()); 189 | QImage image; 190 | image.loadFromData(byteArray); 191 | QPixmap pixmap = QPixmap::fromImage(image); 192 | //显示头像 193 | QLabel *avatorLabel = new QLabel; 194 | avatorLabel->setPixmap(pixmap); 195 | avatorLabel->setScaledContents(true); 196 | avatorLabel->setFixedSize(120, 120); 197 | avatorLabel->setAlignment(Qt::AlignCenter); 198 | avatorLabel->setStyleSheet("border: 3px solid black; border-radius: 8px;"); 199 | ui->layout_frame->addWidget(avatorLabel, 0, Qt::AlignCenter); 200 | //添加间隔器 201 | QSpacerItem *spacer0 = new QSpacerItem(0, 3, QSizePolicy::Fixed, QSizePolicy::Fixed); 202 | ui->layout_frame->addItem(spacer0); 203 | //添加信息 204 | if (!nickname.isEmpty()) ui->layout_frame->addWidget(addTextEditWithStyle("昵称: ", nickname), 0, Qt::AlignCenter); 205 | if (!accountNum.isEmpty()) ui->layout_frame->addWidget(addTextEditWithStyle("账号: ", accountNum), 0, Qt::AlignCenter); 206 | if (!gender.isEmpty()) ui->layout_frame->addWidget(addTextEditWithStyle("性别: ", gender), 0, Qt::AlignCenter); 207 | if (!birthday.isEmpty()) ui->layout_frame->addWidget(addTextEditWithStyle("生日: ", birthday), 0, Qt::AlignCenter); 208 | if (!signature.isEmpty()) ui->layout_frame->addWidget(addTextEditWithStyle("签名: ", signature), 0, Qt::AlignCenter); 209 | //添加间隔器 210 | QSpacerItem *spacer1 = new QSpacerItem(0, 3, QSizePolicy::Fixed, QSizePolicy::Fixed); 211 | ui->layout_frame->addItem(spacer1); 212 | //添加添加好友按钮 213 | QPushButton *addButton = new QPushButton("添加好友"); 214 | addButton->setCursor(Qt::PointingHandCursor); 215 | addButton->setFixedSize(180, 55); 216 | addButton->setStyleSheet( 217 | "QPushButton {" 218 | " font: 12pt 'Microsoft YaHei UI';" 219 | " background-color: rgb(5, 186, 251);" 220 | " color: white;" 221 | " font-weight: bold; " 222 | " border-radius: 15px;" 223 | "}" 224 | "QPushButton:hover {" 225 | " background-color: rgba(5, 186, 251, 0.7);" 226 | " font-weight: bold; " 227 | " color: white;" 228 | " border-radius: 15px;" 229 | "}" 230 | "QPushButton:pressed {" 231 | " background-color: rgba(0, 123, 255, 0.8);" 232 | " font-weight: bold; " 233 | " color: rgba(255, 255, 255, 0.9);" 234 | " border-radius: 15px;" 235 | "}" 236 | ); 237 | ui->layout_frame->addWidget(addButton, 0, Qt::AlignCenter); 238 | //增加间距 239 | ui->layout_frame->setSpacing(3); 240 | ui->layout_frame->setContentsMargins(5, 5, 5, 5); 241 | //添加间隔器 242 | QSpacerItem *spacer2 = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding); 243 | ui->layout_frame->addItem(spacer2); 244 | addButton->setFocusPolicy(Qt::ClickFocus); 245 | //为按钮添加点击事件 246 | connect(addButton, &QPushButton::clicked, this, [&]() { 247 | qDebug() << "添加好友按钮被点击"; 248 | ChoiceDialog dialog(this); 249 | dialog.transText("你确定要添加好友吗?"); 250 | dialog.transButText("确定","取消"); 251 | int result = dialog.exec(); 252 | if (result == QDialog::Accepted) { 253 | emit addFriend(accountNum); 254 | } 255 | }); 256 | } 257 | } 258 | 259 | 260 | void LineSerach_2::focusInEvent(QFocusEvent *event)//搜索框获得焦点 261 | { 262 | setStyleSheet("font: 450 11pt 'Microsoft YaHei UI Light'; " 263 | "border: 1px solid rgba(0, 0, 0, 0.3); " 264 | "border-radius: 5px; " 265 | "border: none;" 266 | "padding:5px;" 267 | "color: black;"); 268 | if(text() == "输入对方账号搜索"){ 269 | setText(""); 270 | } 271 | QLineEdit::focusInEvent(event); 272 | } 273 | 274 | 275 | void LineSerach_2::focusOutEvent(QFocusEvent *event)//搜索失去焦点 276 | { 277 | setStyleSheet("font: 450 11pt 'Microsoft YaHei UI Light'; " 278 | "border: 1px solid rgba(0, 0, 0, 0.3); " 279 | "border-radius: 5px; " 280 | "border: none;" 281 | "padding:5px;" 282 | "color: grey;"); 283 | if (text().isEmpty()) { 284 | setText("输入对方账号搜索"); 285 | setStyleSheet("font: 400 11pt 'Microsoft YaHei UI Light'; " 286 | "border: 1px solid rgba(0, 0, 0, 0.3); " 287 | "border-radius: 5px; " 288 | "border: none;" 289 | "padding:5px;" 290 | "color: grey;"); 291 | } 292 | QLineEdit::focusOutEvent(event); 293 | } 294 | 295 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /user/user/addfriends.h: -------------------------------------------------------------------------------- 1 | #ifndef ADDFRIENDS_H 2 | #define ADDFRIENDS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Ui { 14 | class AddFriends; 15 | } 16 | 17 | 18 | class AddFriends : public QDialog 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit AddFriends(QWidget *parent = nullptr); 24 | ~AddFriends(); 25 | void paintEvent(QPaintEvent *event);//窗口背景 26 | void mousePressEvent(QMouseEvent *event);//捕获鼠标按下事件 27 | void mouseMoveEvent(QMouseEvent *event);//实现拖拽移动效果与调整大小效果 28 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 29 | 30 | protected: 31 | void closeEvent(QCloseEvent *event);//关闭窗口事件 32 | 33 | private slots: 34 | void on_but_deletewindow_clicked();//关闭窗口按钮 35 | void on_line_serach_returnPressed();//搜索好友 36 | void on_but_fangdajing_clicked();//点击放大镜也是搜索 37 | 38 | public slots: 39 | void serachResult(const QJsonObject &json);//查找账号的结果 40 | 41 | signals: 42 | void serachFriends(const QString &account);//向主窗体发送搜索账号信息 43 | void customClose();//向主窗体发送信号 表示已经关闭了 44 | void addFriend(const QString &friendAccount);//向主窗体发送信号 表示添加好友 45 | 46 | private: 47 | Ui::AddFriends *ui; 48 | QString accountNum;//搜索到的账号 49 | QPoint dragPosition; 50 | int moveFlag = 0; 51 | }; 52 | 53 | 54 | class LineSerach_2 :public QLineEdit//搜索框类 55 | { 56 | Q_OBJECT 57 | 58 | public: 59 | LineSerach_2(QWidget *parent = nullptr) : QLineEdit(parent) {} 60 | 61 | public slots: 62 | void focusInEvent(QFocusEvent *event);//搜索框获得焦点 63 | void focusOutEvent(QFocusEvent *event);//搜索失去焦点 64 | }; 65 | 66 | #endif // ADDFRIENDS_H 67 | -------------------------------------------------------------------------------- /user/user/addfriends.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AddFriends 4 | 5 | 6 | 7 | 0 8 | 0 9 | 530 10 | 530 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Qt::ContextMenuPolicy::DefaultContextMenu 21 | 22 | 23 | 添加好友 24 | 25 | 26 | 27 | 28 | 29 | border:none 30 | 31 | 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 0 40 | 15 41 | 42 | 43 | 44 | 45 | 20 46 | 20 47 | 48 | 49 | 50 | 51 | 20 52 | 20 53 | 54 | 55 | 56 | QPushButton { 57 | border: none; 58 | background: transparent; 59 | color: rgb(78, 78, 78); 60 | font: 16pt 'Microsoft New Tai Lue'; 61 | } 62 | 63 | QPushButton:hover { 64 | border: none; 65 | background: transparent; 66 | color: white; 67 | font: 16pt 'Microsoft New Tai Lue'; 68 | background: red; 69 | border-radius: 3px; 70 | } 71 | 72 | 73 | x 74 | 75 | 76 | false 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 0 89 | 0 90 | 91 | 92 | 93 | 94 | 480 95 | 30 96 | 97 | 98 | 99 | 100 | 460 101 | 30 102 | 103 | 104 | 105 | false 106 | 107 | 108 | Qt::FocusPolicy::ClickFocus 109 | 110 | 111 | border-radius: 5px; 112 | border: none; 113 | padding:5px; 114 | font: 400 11pt "Microsoft YaHei UI Light"; 115 | color:grey; 116 | 117 | 118 | 输入对方账号搜索 119 | 120 | 121 | 12 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 0 130 | 0 131 | 132 | 133 | 134 | 135 | 30 136 | 30 137 | 138 | 139 | 140 | PointingHandCursor 141 | 142 | 143 | background:transparent; 144 | border: none; 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | false 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 0 167 | 210 168 | 169 | 170 | 171 | 172 | 0 173 | 210 174 | 175 | 176 | 177 | border-radius: 10px; 178 | border: 0.5px solid rgb(180, 180, 180); 179 | 180 | 181 | 182 | QFrame::Shape::StyledPanel 183 | 184 | 185 | QFrame::Shadow::Raised 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 0 199 | 0 200 | 201 | 202 | 203 | Qt::ContextMenuPolicy::NoContextMenu 204 | 205 | 206 | font: 700 11pt "Microsoft YaHei UI"; 207 | 208 | 209 | 添加好友 210 | 211 | 212 | Qt::AlignmentFlag::AlignCenter 213 | 214 | 215 | 216 | 217 | 218 | 219 | Qt::Orientation::Horizontal 220 | 221 | 222 | QSizePolicy::Policy::Fixed 223 | 224 | 225 | 226 | 1 227 | 20 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | LineSerach_2 237 | QLineEdit 238 |
addfriends.h
239 |
240 |
241 | 242 | 243 |
244 | -------------------------------------------------------------------------------- /user/user/autocleartextedit.cpp: -------------------------------------------------------------------------------- 1 | #include "autocleartextedit.h" 2 | 3 | AutoClearTextEdit::AutoClearTextEdit(QWidget *parent) 4 | : QTextEdit(parent) 5 | { 6 | } 7 | 8 | 9 | AutoClearTextEdit::AutoClearTextEdit(const QString &text, QWidget *parent) 10 | : QTextEdit(parent) 11 | { 12 | setPlainText(text);//设置初始文本 13 | } 14 | 15 | 16 | void AutoClearTextEdit::focusOutEvent(QFocusEvent *event) 17 | { 18 | QTextCursor cursor = this->textCursor(); 19 | cursor.clearSelection();//取消选择 20 | this->setTextCursor(cursor);//更新光标状态 21 | QTextEdit::focusOutEvent(event);//调用基类的事件处理 22 | } 23 | -------------------------------------------------------------------------------- /user/user/autocleartextedit.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTOCLEARTEXTEDIT_H 2 | #define AUTOCLEARTEXTEDIT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class AutoClearTextEdit : public QTextEdit//可以自动取消选择文字的textedit 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit AutoClearTextEdit(QWidget *parent = nullptr); 16 | explicit AutoClearTextEdit(const QString &text, QWidget *parent = nullptr);//新增构造函数 17 | 18 | protected: 19 | void focusOutEvent(QFocusEvent *event) override; 20 | }; 21 | 22 | #endif // AUTOCLEARTEXTEDIT_H 23 | -------------------------------------------------------------------------------- /user/user/changeinformation.cpp: -------------------------------------------------------------------------------- 1 | #include "changeinformation.h" 2 | #include "qpainterpath.h" 3 | #include "ui_changeinformation.h" 4 | #include "dialog.h" 5 | #include "cutavator.h" 6 | 7 | ChangeInformation::ChangeInformation(MyAccountInfo info, QWidget *parent) 8 | : QDialog(parent) 9 | , ui(new Ui::ChangeInformation) 10 | , actInfo(info) 11 | { 12 | ui->setupUi(this); 13 | //初始化窗口 14 | QIcon icon(":/pictures/suliao.png"); 15 | setWindowIcon(icon); 16 | setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); 17 | setAttribute(Qt::WA_TranslucentBackground); 18 | //设置当前页面各信息 19 | setMessage(actInfo); 20 | // 将窗口居中显示 21 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 22 | if (topLevelParent) { 23 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 24 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 25 | move(x, y); 26 | } 27 | } 28 | 29 | 30 | ChangeInformation::~ChangeInformation() 31 | { 32 | delete ui; 33 | qDebug()<<"修改个人信息窗口析构函数被调用"; 34 | disconnect(); 35 | } 36 | 37 | 38 | void ChangeInformation::paintEvent(QPaintEvent *event)//窗口背景 39 | { 40 | //调用基类方法以处理父类的绘图 41 | QDialog::paintEvent(event); 42 | QPainter painter(this); 43 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 44 | //加载背景图片 45 | QPixmap background(":/pictures/094 Cloudy Apple - trans.png"); 46 | //确保图片已加载 47 | if (background.isNull()) { 48 | qWarning("背景图像加载失败"); 49 | return; 50 | } 51 | QSize newSize = QSize(this->width(), this->height()); 52 | //将背景图缩放为新的大小 53 | QPixmap scaledBackground = background.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 54 | //计算绘制的位置,保持居中 55 | int x = (this->width() - scaledBackground.width()) / 2; 56 | int y = (this->height() - scaledBackground.height()) / 2; 57 | //设置剪裁区域以适应圆角窗口 58 | int radius = 10; 59 | QPainterPath path; 60 | path.addRoundedRect(rect(), radius, radius); 61 | painter.setClipPath(path); 62 | //绘制背景图片 63 | painter.drawPixmap(x, y, scaledBackground); 64 | //绘制边框 65 | painter.setPen(QPen(Qt::gray, 3.5)); 66 | painter.drawRoundedRect(rect(), radius, radius); 67 | } 68 | 69 | 70 | void ChangeInformation::mousePressEvent(QMouseEvent *event)//捕获鼠标按下事件 71 | { 72 | //清除焦点 73 | QList widgets = this->findChildren(); 74 | for (QWidget* widget : widgets) { 75 | widget->clearFocus(); 76 | } 77 | QPoint pos = event->pos(); 78 | int margin = 30; 79 | if (pos.x() <= 30 || pos.x() >= width() - 30 || 80 | pos.y() <= 30 || pos.y() >= height() - 30){//如果点击在边缘 81 | qDebug() << "点击在边缘"; 82 | moveFlag = 1; 83 | dragPosition = event->globalPosition().toPoint() - this->frameGeometry().topLeft();//记录鼠标相对于窗口的初始偏移 84 | event->accept(); 85 | } 86 | } 87 | 88 | 89 | void ChangeInformation::mouseMoveEvent(QMouseEvent *event)//实现拖拽移动效果与调整大小效果 90 | { 91 | qDebug()<<"鼠标位移了"; 92 | QPoint globalPos = event->globalPosition().toPoint();//获取当前的鼠标位置 93 | QPoint delta = globalPos - (this->frameGeometry().topLeft() + dragPosition);//计算当前鼠标位置与窗口之间的相对偏移 94 | if (event->buttons() & Qt::LeftButton) { 95 | if (moveFlag == 1) { 96 | this->move(globalPos - dragPosition); 97 | event->accept(); 98 | } 99 | //更新拖动位置 100 | dragPosition = globalPos - this->frameGeometry().topLeft(); 101 | } 102 | } 103 | 104 | 105 | void ChangeInformation::mouseReleaseEvent(QMouseEvent *event)//重置移动状态 106 | { 107 | moveFlag = 0; 108 | } 109 | 110 | 111 | QString ChangeInformation::pixmapToBase64(const QPixmap &pixmap)//图片转换成base64格式 112 | { 113 | QImage image = pixmap.toImage(); 114 | QBuffer buffer; 115 | buffer.open(QIODevice::WriteOnly); 116 | image.save(&buffer, "PNG"); 117 | QByteArray byteArray = buffer.data(); 118 | return QString(byteArray.toBase64()); 119 | } 120 | 121 | 122 | QPixmap ChangeInformation::base64ToPixmap(const QString &base64Str)//将base64转换为图片 123 | { 124 | QByteArray byteArray = QByteArray::fromBase64(base64Str.toUtf8()); 125 | QImage image; 126 | //尝试加载PNG格式 127 | if (!image.loadFromData(byteArray, "PNG")) { 128 | //如果PNG加载失败,尝试JPG格式 129 | image.loadFromData(byteArray, "JPG"); 130 | } 131 | return QPixmap::fromImage(image); 132 | } 133 | 134 | 135 | void ChangeInformation::setMessage(const MyAccountInfo &info)//设置当前页面各信息 136 | { 137 | ui->textEdit_account->setText(info.account); 138 | ui->line_nickname->setText(info.name); 139 | ui->line_sig->setText(info.signature); 140 | QPixmap avator = base64ToPixmap(info.avator_base64); 141 | ui->lab_avator->setScaledContents(true); 142 | ui->lab_avator->setPixmap(avator); 143 | if(info.gender == "其他"){ 144 | ui->cbbox_sex->setCurrentIndex(0); 145 | } 146 | else if(info.gender == "男"){ 147 | ui->cbbox_sex->setCurrentIndex(1); 148 | } 149 | else{ 150 | ui->cbbox_sex->setCurrentIndex(2); 151 | } 152 | } 153 | 154 | 155 | void ChangeInformation::judgeMessage()//判断能否点击确认 156 | { 157 | int flag = 0;//初始不可点击 158 | if(avaFlag == 1){//头像修改了 则标记可点击 159 | flag = 1; 160 | } 161 | if(ui->line_nickname->text() != actInfo.name || ui->line_sig->text() != actInfo.signature || ui->cbbox_sex->currentText() != actInfo.gender){ 162 | flag = 1;//有信息修改过 则标记可点击 163 | } 164 | if(ui->line_nickname->text() == ""){//任何情况昵称为空 则不可修改 165 | flag = 0; 166 | } 167 | if(flag == 0){ 168 | ui->but_yes->setStyleSheet( 169 | "QPushButton {" 170 | "font: 12pt 'Microsoft YaHei UI';" 171 | "background-color: rgb(167, 214, 255); " 172 | "color: white;" 173 | "border-radius: 10px;" 174 | "}" 175 | ); 176 | ui->but_yes->setEnabled(false); 177 | } 178 | else{ 179 | ui->but_yes->setStyleSheet( 180 | "QPushButton {" 181 | "font: 12pt 'Microsoft YaHei UI';" 182 | "background-color: rgb(5, 186, 251);" 183 | "color: white;" 184 | "border-radius: 10px;" 185 | "border: 0.5px solid rgb(220, 220, 220);" 186 | "}" 187 | "QPushButton:hover {" 188 | "background-color: rgba(5, 186, 251, 0.7);" 189 | "color: white;" 190 | "border-radius: 10px;" 191 | "}" 192 | "QPushButton:pressed {" 193 | "background-color: rgba(0, 123, 255, 0.8);" 194 | "color: rgba(255, 255, 255, 0.9);" 195 | "border-radius: 10px;" 196 | "}" 197 | ); 198 | ui->but_yes->setEnabled(true); 199 | } 200 | } 201 | 202 | 203 | void ChangeInformation::on_but_cancelwindow_clicked()//关闭窗口 204 | { 205 | emit customClose(); 206 | this->close(); 207 | this->deleteLater(); 208 | } 209 | 210 | 211 | void ChangeInformation::on_but_no_clicked()//点击取消 也关闭窗口 212 | { 213 | on_but_cancelwindow_clicked(); 214 | } 215 | 216 | 217 | void ChangeInformation::on_cbbox_sex_currentIndexChanged(int index)//改变性别 判断能否点击确认 218 | { 219 | judgeMessage(); 220 | } 221 | 222 | 223 | void ChangeInformation::on_line_nickname_textChanged(const QString &arg1)//昵称文本框文字改变 判断是否能点击确认 224 | { 225 | judgeMessage(); 226 | } 227 | 228 | 229 | void ChangeInformation::on_line_sig_textChanged(const QString &arg1)//个性签名文本框改变 判断是否能点击确认 230 | { 231 | judgeMessage(); 232 | } 233 | 234 | 235 | void ChangeInformation::on_but_yes_clicked()//发送修改申请 236 | { 237 | MyAccountInfo tmpInfo; 238 | tmpInfo.account = ui->textEdit_account->toPlainText(); 239 | tmpInfo.signature = ui->line_sig->text(); 240 | tmpInfo.gender = ui->cbbox_sex->currentText(); 241 | tmpInfo.name = ui->line_nickname->text(); 242 | tmpInfo.avator_base64 = pixmapToBase64(ui->lab_avator->pixmap()); 243 | sendMessage(tmpInfo); 244 | ui->but_yes->setEnabled(false); 245 | } 246 | 247 | 248 | void ChangeInformation::getAva(const QPixmap &pixmap)//子窗口剪切好头像 收到头像 更新并判断能否点击确认 249 | { 250 | ui->lab_avator->setPixmap(pixmap); 251 | avaFlag = 1; 252 | judgeMessage(); 253 | } 254 | 255 | 256 | void ChangeInformation::dealResult(const QJsonObject &json)//处理修改资料的结果 257 | { 258 | if(json["answer"] == "succeed"){//成功则修改个人资料 259 | actInfo.account = json["account"].toString(); 260 | actInfo.name = json["nickname"].toString(); 261 | actInfo.gender = json["gender"].toString(); 262 | actInfo.signature = json["signature"].toString(); 263 | actInfo.avator_base64 = json["avator"].toString(); 264 | setMessage(actInfo);//重新设置个人资料 265 | avaFlag = 0; 266 | judgeMessage();//判断是否可以点击 267 | QString text = "修改成功!"; 268 | Dialog* dialog = new Dialog(this); 269 | dialog->transText(text); 270 | dialog->exec(); 271 | emit customClose(); 272 | close(); 273 | } 274 | else if(json["answer"] == "fail"){ 275 | qDebug()<<"修改资料失败"; 276 | QString text = "修改失败!"; 277 | Dialog* dialog = new Dialog(this); 278 | dialog->transText(text); 279 | dialog->exec(); 280 | judgeMessage();//判断是否可以点击 281 | } 282 | } 283 | 284 | 285 | void LineMessage::focusInEvent(QFocusEvent *event)//获得焦点处理事件 286 | { 287 | if(flag == 0){ 288 | setText(""); 289 | flag = 1; 290 | } 291 | QLineEdit::focusInEvent(event); 292 | } 293 | 294 | 295 | void LineMessage::focusOutEvent(QFocusEvent *event)//失去焦点处理事件 296 | { 297 | QLineEdit::focusOutEvent(event); 298 | } 299 | 300 | 301 | void LabelChooseAva::mousePressEvent(QMouseEvent *event)//点击头像更换头像 302 | { 303 | qDebug() << "点击头像了"; 304 | QString filename = QFileDialog::getOpenFileName(this, "选择图片", "", "Images (*.png *.jpg *.jpeg *.bmp *.gif)"); 305 | if (!filename.isEmpty()) { 306 | qDebug() << "头像路径有效"; 307 | QPixmap pixmap(filename); 308 | if (pixmap.isNull()) { 309 | qDebug() << "加载图片失败"; 310 | return; 311 | } 312 | //打开头像编辑器 313 | CutAvator *cutter = new CutAvator(filename); 314 | cutter->setWindowFlags(Qt::WindowStaysOnTopHint|Qt::Dialog); 315 | connect(cutter,&CutAvator::cutOk,qobject_cast(this->parentWidget()->parentWidget()),&ChangeInformation::getAva); 316 | cutter->exec(); 317 | cutter->deleteLater(); 318 | } 319 | } 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | -------------------------------------------------------------------------------- /user/user/changeinformation.h: -------------------------------------------------------------------------------- 1 | #ifndef CHANGEINFORMATION_H 2 | #define CHANGEINFORMATION_H 3 | 4 | #include "qlineedit.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace Ui { 15 | class ChangeInformation; 16 | } 17 | 18 | 19 | struct MyAccountInfo { 20 | QString account; 21 | QString name; 22 | QString avator_base64; 23 | QString gender; 24 | QString signature; 25 | }; 26 | 27 | 28 | class ChangeInformation : public QDialog 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | explicit ChangeInformation(MyAccountInfo info, QWidget *parent = nullptr); 34 | ~ChangeInformation(); 35 | void paintEvent(QPaintEvent *event);//窗口背景 36 | void mousePressEvent(QMouseEvent *event);//捕获鼠标按下事件 37 | void mouseMoveEvent(QMouseEvent *event);//实现拖拽移动效果与调整大小效果 38 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 39 | QString pixmapToBase64(const QPixmap &pixmap);//图片转换成base64格式 40 | QPixmap base64ToPixmap(const QString &base64Str);//将base64转换为图片 41 | void setMessage(const MyAccountInfo &info);//设置当前页面各信息 42 | void judgeMessage();//判断能否点击确认 43 | 44 | private slots: 45 | void on_but_cancelwindow_clicked();//关闭窗口 46 | void on_but_no_clicked();//点击取消 也关闭窗口 47 | void on_cbbox_sex_currentIndexChanged(int index);//改变性别 判断能否点击确认 48 | void on_line_nickname_textChanged(const QString &arg1);//昵称文本框文字改变 判断是否能点击确认 49 | void on_line_sig_textChanged(const QString &arg1);//个性签名文本框改变 判断是否能点击确认 50 | void on_but_yes_clicked();//发送修改申请 51 | 52 | public slots: 53 | void getAva(const QPixmap &pixmap);//子窗口剪切好头像 收到头像 更新并判断能否点击确认 54 | void dealResult(const QJsonObject &json);//处理修改资料的结果 55 | 56 | signals: 57 | void customClose();//告诉主窗口要关闭了 58 | void sendMessage(const MyAccountInfo& info);//告诉主窗口 发送新的信息 59 | 60 | private: 61 | Ui::ChangeInformation *ui; 62 | MyAccountInfo actInfo; // 存储账号信息 63 | QPoint dragPosition; 64 | int moveFlag = 0; 65 | int avaFlag = 0;//判断头像是不是更新过 66 | }; 67 | 68 | 69 | class LineMessage:public QLineEdit//输入框类 70 | { 71 | Q_OBJECT 72 | 73 | public: 74 | LineMessage(QWidget *parent = nullptr) : QLineEdit(parent) {} 75 | 76 | public slots: 77 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 78 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 79 | 80 | private: 81 | int flag = 0;//标记是不是第一次点击 82 | }; 83 | 84 | 85 | class LabelChooseAva:public QLabel//点击头像更换头像 86 | { 87 | Q_OBJECT 88 | 89 | public: 90 | LabelChooseAva(QWidget *parent=nullptr):QLabel(parent){} 91 | void mousePressEvent(QMouseEvent *event);//点击头像更换头像 92 | }; 93 | #endif // CHANGEINFORMATION_H 94 | -------------------------------------------------------------------------------- /user/user/changepassword.cpp: -------------------------------------------------------------------------------- 1 | #include "changepassword.h" 2 | #include "ui_changepassword.h" 3 | #include "dialog.h" 4 | 5 | ChangePassword::ChangePassword(QWidget *parent) 6 | : QDialog(parent) 7 | , ui(new Ui::ChangePassword) 8 | { 9 | ui->setupUi(this); 10 | //初始化窗口 11 | QIcon icon(":/pictures/suliao.png"); 12 | setWindowIcon(icon); 13 | setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); 14 | setAttribute(Qt::WA_TranslucentBackground); 15 | // 将窗口居中显示 16 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 17 | if (topLevelParent) { 18 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 19 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 20 | move(x, y); 21 | } 22 | } 23 | 24 | 25 | ChangePassword::~ChangePassword() 26 | { 27 | delete ui; 28 | } 29 | 30 | 31 | void ChangePassword::setVal()//设置输入验证器 32 | { 33 | QRegularExpression regExp("^[a-zA-Z0-9]{1,12}$");//给输入框设置验证器 34 | validator = new QRegularExpressionValidator(regExp, this); 35 | ui->line_account->setValidator(validator); 36 | ui->line_password->setValidator(validator); 37 | ui->line_newpassword->setValidator(validator); 38 | ui->line_newpassword2->setValidator(validator); 39 | } 40 | 41 | 42 | void ChangePassword::paintEvent(QPaintEvent *event)//窗口背景 43 | { 44 | //调用基类方法以处理父类的绘图 45 | QDialog::paintEvent(event); 46 | QPainter painter(this); 47 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 48 | //加载背景图片 49 | QPixmap background(":/pictures/094 Cloudy Apple - trans.png"); 50 | //确保图片已加载 51 | if (background.isNull()) { 52 | qWarning("背景图像加载失败"); 53 | return; 54 | } 55 | QSize newSize = QSize(this->width(), this->height()); 56 | //将背景图缩放为新的大小 57 | QPixmap scaledBackground = background.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 58 | //计算绘制的位置,保持居中 59 | int x = (this->width() - scaledBackground.width()) / 2; 60 | int y = (this->height() - scaledBackground.height()) / 2; 61 | //设置剪裁区域以适应圆角窗口 62 | int radius = 10; 63 | QPainterPath path; 64 | path.addRoundedRect(rect(), radius, radius); 65 | painter.setClipPath(path); 66 | //绘制背景图片 67 | painter.drawPixmap(x, y, scaledBackground); 68 | //绘制边框 69 | painter.setPen(QPen(Qt::gray, 3.5)); 70 | painter.drawRoundedRect(rect(), radius, radius); 71 | } 72 | 73 | 74 | void ChangePassword::mousePressEvent(QMouseEvent *event)//捕获鼠标按下事件 75 | { 76 | //清除焦点 77 | QList widgets = this->findChildren(); 78 | for (QWidget* widget : widgets) { 79 | widget->clearFocus(); 80 | } 81 | QPoint pos = event->pos(); 82 | int margin = 30; 83 | if (pos.x() <= 30 || pos.x() >= width() - 30 || 84 | pos.y() <= 30 || pos.y() >= height() - 30){//如果点击在边缘 85 | qDebug() << "点击在边缘"; 86 | moveFlag = 1; 87 | dragPosition = event->globalPosition().toPoint() - this->frameGeometry().topLeft();//记录鼠标相对于窗口的初始偏移 88 | event->accept(); 89 | } 90 | } 91 | 92 | 93 | void ChangePassword::mouseMoveEvent(QMouseEvent *event)//实现拖拽移动效果与调整大小效果 94 | { 95 | qDebug()<<"鼠标位移了"; 96 | QPoint globalPos = event->globalPosition().toPoint();//获取当前的鼠标位置 97 | QPoint delta = globalPos - (this->frameGeometry().topLeft() + dragPosition);//计算当前鼠标位置与窗口之间的相对偏移 98 | if (event->buttons() & Qt::LeftButton) { 99 | if (moveFlag == 1) { 100 | this->move(globalPos - dragPosition); 101 | event->accept(); 102 | } 103 | //更新拖动位置 104 | dragPosition = globalPos - this->frameGeometry().topLeft(); 105 | } 106 | } 107 | 108 | 109 | void ChangePassword::mouseReleaseEvent(QMouseEvent *event)//重置移动状态 110 | { 111 | moveFlag = 0; 112 | } 113 | 114 | 115 | void ChangePassword:: closeEvent(QCloseEvent *event)//关闭窗口事件 116 | { 117 | emit customClose();//this->disconnect();放在主窗口的槽函数了 118 | this->deleteLater(); 119 | event->accept(); 120 | } 121 | 122 | 123 | void ChangePassword::on_but_deletewindow_clicked()//关闭按钮 124 | { 125 | this->close(); 126 | } 127 | 128 | 129 | void ChangePassword::on_line_account_textChanged(const QString &arg1) 130 | { 131 | if(ui->line_account->text() != "" && ui->line_account->text() != "请输入您的账号" 132 | && ui->line_password->text() != "" && ui->line_password->text() != "请输入您的密码"){ 133 | ui->but_yes->setEnabled(true); 134 | ui->but_yes->setStyleSheet( 135 | "QPushButton {" 136 | "font: 12pt 'Microsoft YaHei UI';" 137 | "background-color: rgb(5, 186, 251);" 138 | "color: white;" 139 | "border-radius: 10px;" 140 | "border: 0.5px solid rgb(220, 220, 220);" 141 | "}" 142 | "QPushButton:hover {" 143 | "background-color: rgba(5, 186, 251, 0.7);" 144 | "color: white;" 145 | "border-radius: 10px;" 146 | "}" 147 | "QPushButton:pressed {" 148 | "background-color: rgba(0, 123, 255, 0.8);" 149 | "color: rgba(255, 255, 255, 0.9);" 150 | "border-radius: 10px;" 151 | "}" 152 | ); 153 | } 154 | else{ 155 | ui->but_yes->setEnabled(false); 156 | ui->but_yes->setStyleSheet( 157 | "QPushButton {" 158 | "font: 12pt 'Microsoft YaHei UI';" 159 | "background-color: rgb(167, 214, 255); " 160 | "color: white;" 161 | "border-radius: 10px;" 162 | "}" 163 | ); 164 | } 165 | } 166 | 167 | 168 | void ChangePassword::on_line_password_textChanged(const QString &arg1)//第一个页面判断能否点击确认按钮 169 | { 170 | if(ui->line_account->text() != "" && ui->line_account->text() != "请输入您的账号" 171 | && ui->line_password->text() != "" && ui->line_password->text() != "请输入您的密码"){ 172 | ui->but_yes->setEnabled(true); 173 | ui->but_yes->setStyleSheet( 174 | "QPushButton {" 175 | "font: 12pt 'Microsoft YaHei UI';" 176 | "background-color: rgb(5, 186, 251);" 177 | "color: white;" 178 | "border-radius: 10px;" 179 | "border: 0.5px solid rgb(220, 220, 220);" 180 | "}" 181 | "QPushButton:hover {" 182 | "background-color: rgba(5, 186, 251, 0.7);" 183 | "color: white;" 184 | "border-radius: 10px;" 185 | "}" 186 | "QPushButton:pressed {" 187 | "background-color: rgba(0, 123, 255, 0.8);" 188 | "color: rgba(255, 255, 255, 0.9);" 189 | "border-radius: 10px;" 190 | "}" 191 | ); 192 | } 193 | else{ 194 | ui->but_yes->setEnabled(false); 195 | ui->but_yes->setStyleSheet( 196 | "QPushButton {" 197 | "font: 12pt 'Microsoft YaHei UI';" 198 | "background-color: rgb(167, 214, 255); " 199 | "color: white;" 200 | "border-radius: 10px;" 201 | "}" 202 | ); 203 | } 204 | } 205 | 206 | void ChangePassword::on_line_newpassword_textChanged(const QString &arg1)//第二个页面判断能否点击确认按钮 207 | { 208 | if(ui->line_newpassword->text() != "" && ui->line_newpassword->text() != "请输入新的密码" 209 | && ui->line_newpassword2->text() != "" && ui->line_newpassword2->text() != "请确认您的密码"){ 210 | ui->but_yes_2->setEnabled(true); 211 | ui->but_yes_2->setStyleSheet( 212 | "QPushButton {" 213 | "font: 12pt 'Microsoft YaHei UI';" 214 | "background-color: rgb(5, 186, 251);" 215 | "color: white;" 216 | "border-radius: 10px;" 217 | "border: 0.5px solid rgb(220, 220, 220);" 218 | "}" 219 | "QPushButton:hover {" 220 | "background-color: rgba(5, 186, 251, 0.7);" 221 | "color: white;" 222 | "border-radius: 10px;" 223 | "}" 224 | "QPushButton:pressed {" 225 | "background-color: rgba(0, 123, 255, 0.8);" 226 | "color: rgba(255, 255, 255, 0.9);" 227 | "border-radius: 10px;" 228 | "}" 229 | ); 230 | } 231 | else{ 232 | ui->but_yes_2->setEnabled(false); 233 | ui->but_yes_2->setStyleSheet( 234 | "QPushButton {" 235 | "font: 12pt 'Microsoft YaHei UI';" 236 | "background-color: rgb(167, 214, 255); " 237 | "color: white;" 238 | "border-radius: 10px;" 239 | "}" 240 | ); 241 | } 242 | } 243 | 244 | 245 | void ChangePassword::on_line_newpassword2_textChanged(const QString &arg1)//第二个页面判断能否点击确认按钮 246 | { 247 | if(ui->line_newpassword->text() != "" && ui->line_newpassword->text() != "请输入新的密码" 248 | && ui->line_newpassword2->text() != "" && ui->line_newpassword2->text() != "请确认您的密码"){ 249 | ui->but_yes_2->setEnabled(true); 250 | ui->but_yes_2->setStyleSheet( 251 | "QPushButton {" 252 | "font: 12pt 'Microsoft YaHei UI';" 253 | "background-color: rgb(5, 186, 251);" 254 | "color: white;" 255 | "border-radius: 10px;" 256 | "border: 0.5px solid rgb(220, 220, 220);" 257 | "}" 258 | "QPushButton:hover {" 259 | "background-color: rgba(5, 186, 251, 0.7);" 260 | "color: white;" 261 | "border-radius: 10px;" 262 | "}" 263 | "QPushButton:pressed {" 264 | "background-color: rgba(0, 123, 255, 0.8);" 265 | "color: rgba(255, 255, 255, 0.9);" 266 | "border-radius: 10px;" 267 | "}" 268 | ); 269 | } 270 | else{ 271 | ui->but_yes_2->setEnabled(false); 272 | ui->but_yes_2->setStyleSheet( 273 | "QPushButton {" 274 | "font: 12pt 'Microsoft YaHei UI';" 275 | "background-color: rgb(167, 214, 255); " 276 | "color: white;" 277 | "border-radius: 10px;" 278 | "}" 279 | ); 280 | } 281 | } 282 | 283 | 284 | void ChangePassword::on_but_yes_clicked()//告知主窗体发送账号密码 285 | { 286 | QJsonObject jsonObj; 287 | jsonObj["tag"] = "changepassword1"; 288 | jsonObj["account"] = ui->line_account->text(); 289 | jsonObj["password"] = ui->line_password->text(); 290 | emit changePassword1(jsonObj); 291 | ui->line_account->setEnabled(false); 292 | ui->line_password->setEnabled(false); 293 | ui->but_yes->setEnabled(false); 294 | } 295 | 296 | 297 | void ChangePassword::on_but_yes_2_clicked()//告知主窗体发送修改密码 298 | { 299 | if(ui->line_newpassword->text() != ui->line_newpassword2->text()){ 300 | QString text = "您的两次密码不一致。"; 301 | Dialog* dialog = new Dialog(this); 302 | dialog->transText(text); 303 | dialog->exec(); 304 | return; 305 | } 306 | QJsonObject jsonObj; 307 | jsonObj["tag"] = "changepassword2"; 308 | jsonObj["account"] = ui->line_account->text(); 309 | jsonObj["password"] = ui->line_newpassword->text(); 310 | emit changePassword2(jsonObj); 311 | ui->line_newpassword->setEnabled(false); 312 | ui->line_newpassword2->setEnabled(false); 313 | ui->but_yes_2->setEnabled(false); 314 | } 315 | 316 | 317 | void ChangePassword::changePasswordAns1(const QJsonObject& json)//修改账号密码第一个申请的结果 318 | { 319 | if(json ["answer"] == "fail"){ 320 | ui->line_account->setEnabled(true); 321 | ui->line_password->setEnabled(true); 322 | ui->but_yes->setEnabled(true); 323 | QString text = "请求失败。"; 324 | Dialog* dialog = new Dialog(this); 325 | dialog->transText(text); 326 | dialog->exec(); 327 | return; 328 | 329 | } 330 | else if(json ["answer"] == "user_not_found"){ 331 | ui->line_account->setEnabled(true); 332 | ui->line_password->setEnabled(true); 333 | ui->but_yes->setEnabled(true); 334 | QString text = "账号或密码错误,请检查。"; 335 | Dialog* dialog = new Dialog(this); 336 | dialog->transText(text); 337 | dialog->exec(); 338 | return; 339 | } 340 | else if(json ["answer"] == "succeed"){ 341 | ui->stackedWidget->setCurrentIndex(1); 342 | } 343 | } 344 | 345 | 346 | void ChangePassword::changePasswordAns2(const QJsonObject& json)//修改账号密码第二个申请的结果 347 | { 348 | if(json ["answer"] == "fail"){ 349 | QString text = "请求失败。"; 350 | Dialog* dialog = new Dialog(this); 351 | dialog->transText(text); 352 | dialog->exec(); 353 | this->close(); 354 | return; 355 | 356 | } 357 | else if(json ["answer"] == "succeed"){ 358 | QString text = "修改成功!"; 359 | Dialog* dialog = new Dialog(this); 360 | dialog->transText(text); 361 | dialog->exec(); 362 | this->close(); 363 | return; 364 | } 365 | } 366 | 367 | 368 | void LineChangePass::focusInEvent(QFocusEvent *event)//获得焦点处理事件 369 | { 370 | if(text() == "请输入您的账号" || text() == "请输入您的密码" || text() == "请输入新的密码" || text() == "请确认您的密码"){ 371 | setText(""); 372 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 373 | "border: 1px solid rgba(0, 0, 0, 0.1);" 374 | "border-radius: 8px;" 375 | "padding: 5px;" 376 | "color: black;"); 377 | } 378 | if(objectName() == "line_newpassword" || objectName() == "line_newpassword2" || objectName() == "line_password"){ 379 | this->setEchoMode(Password); 380 | } 381 | QLineEdit::focusInEvent(event); 382 | } 383 | 384 | 385 | void LineChangePass::focusOutEvent(QFocusEvent *event)//失去焦点处理事件 386 | { 387 | if(text() == ""){ 388 | if(objectName() == "line_accont") 389 | { 390 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 391 | "border: 1px solid rgba(0, 0, 0, 0.1);" 392 | "border-radius: 8px;" 393 | "padding: 5px;" 394 | "color: grey;"); 395 | setText("请输入您的账号"); 396 | } 397 | if(objectName() == "line_password") 398 | { 399 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 400 | "border: 1px solid rgba(0, 0, 0, 0.1);" 401 | "border-radius: 8px;" 402 | "padding: 5px;" 403 | "color: grey;"); 404 | setText("请输入您的密码"); 405 | setEchoMode(Normal); 406 | } 407 | if(objectName() == "line_newpassword") 408 | { 409 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 410 | "border: 1px solid rgba(0, 0, 0, 0.1);" 411 | "border-radius: 8px;" 412 | "padding: 5px;" 413 | "color: grey;"); 414 | setText("请输入新的密码"); 415 | setEchoMode(Normal); 416 | } 417 | if(objectName() == "line_newpassword2") 418 | { 419 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 420 | "border: 1px solid rgba(0, 0, 0, 0.1);" 421 | "border-radius: 8px;" 422 | "padding: 5px;" 423 | "color: grey;"); 424 | setText("请确认您的密码"); 425 | setEchoMode(Normal); 426 | } 427 | } 428 | QLineEdit::focusOutEvent(event); 429 | } 430 | 431 | 432 | -------------------------------------------------------------------------------- /user/user/changepassword.h: -------------------------------------------------------------------------------- 1 | #ifndef CHANGEPASSWORD_H 2 | #define CHANGEPASSWORD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Ui { 14 | class ChangePassword; 15 | } 16 | 17 | class ChangePassword : public QDialog 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit ChangePassword(QWidget *parent = nullptr); 23 | ~ChangePassword(); 24 | void setVal();//设置输入验证器 25 | void paintEvent(QPaintEvent *event);//窗口背景 26 | void mousePressEvent(QMouseEvent *event);//捕获鼠标按下事件 27 | void mouseMoveEvent(QMouseEvent *event);//实现拖拽移动效果与调整大小效果 28 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 29 | void closeEvent(QCloseEvent *event);//关闭窗口事件 30 | 31 | private slots: 32 | void on_but_deletewindow_clicked();//关闭按钮 33 | void on_line_account_textChanged(const QString &arg1);//第一个页面判断能否点击确认按钮 34 | void on_line_password_textChanged(const QString &arg1);//第一个页面判断能否点击确认按钮 35 | void on_line_newpassword_textChanged(const QString &arg1);//第二个页面判断能否点击确认按钮 36 | void on_line_newpassword2_textChanged(const QString &arg1);//第二个页面判断能否点击确认按钮 37 | void on_but_yes_clicked();//告知主窗体发送账号密码 38 | void on_but_yes_2_clicked();//告知主窗体发送修改密码 39 | 40 | public slots: 41 | void changePasswordAns1(const QJsonObject& json);//修改账号密码第一个申请的结果 42 | void changePasswordAns2(const QJsonObject& json);//修改账号密码第二个申请的结果 43 | 44 | signals: 45 | void customClose();//通知主窗体要关闭了 46 | void changePassword1(const QJsonObject &json);//告知主窗体发送修改申请 47 | void changePassword2(const QJsonObject &json);//告知主窗体发送最终修改申请 48 | 49 | private: 50 | Ui::ChangePassword *ui; 51 | int moveFlag = 0; 52 | QPoint dragPosition; 53 | QValidator *validator; 54 | }; 55 | 56 | 57 | class LineChangePass:public QLineEdit//输入框类 58 | { 59 | Q_OBJECT 60 | 61 | public: 62 | LineChangePass(QWidget *parent = nullptr) : QLineEdit(parent) {} 63 | 64 | public slots: 65 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 66 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 67 | }; 68 | 69 | #endif // CHANGEPASSWORD_H 70 | -------------------------------------------------------------------------------- /user/user/changepassword.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ChangePassword 4 | 5 | 6 | 7 | 0 8 | 0 9 | 322 10 | 217 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | Qt::ContextMenuPolicy::NoContextMenu 21 | 22 | 23 | border:none; 24 | 25 | 26 | 0 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 0 37 | 0 38 | 39 | 40 | 41 | font: 12pt "Microsoft YaHei UI"; 42 | border:none; 43 | color:black; 44 | 45 | 46 | 47 | 输入账号: 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 0 56 | 0 57 | 58 | 59 | 60 | 61 | 224 62 | 38 63 | 64 | 65 | 66 | 67 | 224 68 | 38 69 | 70 | 71 | 72 | Qt::FocusPolicy::ClickFocus 73 | 74 | 75 | font: 12pt "Microsoft YaHei UI"; 76 | border: 1px solid rgba(0, 0, 0, 0.1); 77 | border-radius: 8px; 78 | padding:5px; 79 | color:grey; 80 | 81 | 82 | 83 | 84 | 请输入您的账号 85 | 86 | 87 | 12 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 0 100 | 0 101 | 102 | 103 | 104 | font: 12pt "Microsoft YaHei UI"; 105 | border:none; 106 | color:black; 107 | 108 | 109 | 110 | 输入密码: 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 0 119 | 0 120 | 121 | 122 | 123 | 124 | 224 125 | 38 126 | 127 | 128 | 129 | 130 | 224 131 | 38 132 | 133 | 134 | 135 | Qt::FocusPolicy::ClickFocus 136 | 137 | 138 | font: 12pt "Microsoft YaHei UI"; 139 | border: 1px solid rgba(0, 0, 0, 0.1); 140 | border-radius: 8px; 141 | padding:5px; 142 | color:grey; 143 | 144 | 145 | 146 | 147 | 请输入您的密码 148 | 149 | 150 | 12 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | Qt::Orientation::Horizontal 162 | 163 | 164 | 165 | 40 166 | 20 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | false 175 | 176 | 177 | 178 | 0 179 | 0 180 | 181 | 182 | 183 | 184 | 175 185 | 35 186 | 187 | 188 | 189 | PointingHandCursor 190 | 191 | 192 | QPushButton { 193 | font: 12pt "Microsoft YaHei UI"; 194 | background-color: rgb(167, 214, 255); 195 | color: white; 196 | border-radius: 10px; 197 | } 198 | 199 | 200 | 201 | 确认 202 | 203 | 204 | 205 | 206 | 207 | 208 | Qt::Orientation::Horizontal 209 | 210 | 211 | 212 | 40 213 | 20 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 0 231 | 0 232 | 233 | 234 | 235 | font: 12pt "Microsoft YaHei UI"; 236 | border:none; 237 | color:black; 238 | 239 | 240 | 241 | 新的密码: 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 0 250 | 0 251 | 252 | 253 | 254 | 255 | 224 256 | 38 257 | 258 | 259 | 260 | 261 | 224 262 | 38 263 | 264 | 265 | 266 | Qt::FocusPolicy::ClickFocus 267 | 268 | 269 | font: 12pt "Microsoft YaHei UI"; 270 | border: 1px solid rgba(0, 0, 0, 0.1); 271 | border-radius: 8px; 272 | padding:5px; 273 | color:grey; 274 | 275 | 276 | 277 | 278 | 请输入新的密码 279 | 280 | 281 | 12 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 0 294 | 0 295 | 296 | 297 | 298 | font: 12pt "Microsoft YaHei UI"; 299 | border:none; 300 | color:black; 301 | 302 | 303 | 304 | 确认密码: 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 0 313 | 0 314 | 315 | 316 | 317 | 318 | 224 319 | 38 320 | 321 | 322 | 323 | 324 | 224 325 | 38 326 | 327 | 328 | 329 | Qt::FocusPolicy::ClickFocus 330 | 331 | 332 | font: 12pt "Microsoft YaHei UI"; 333 | border: 1px solid rgba(0, 0, 0, 0.1); 334 | border-radius: 8px; 335 | padding:5px; 336 | color:grey; 337 | 338 | 339 | 340 | 341 | 请确认您的密码 342 | 343 | 344 | 12 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | Qt::Orientation::Horizontal 356 | 357 | 358 | 359 | 40 360 | 20 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | false 369 | 370 | 371 | 372 | 0 373 | 0 374 | 375 | 376 | 377 | 378 | 175 379 | 35 380 | 381 | 382 | 383 | PointingHandCursor 384 | 385 | 386 | QPushButton { 387 | font: 12pt "Microsoft YaHei UI"; 388 | background-color: rgb(167, 214, 255); 389 | color: white; 390 | border-radius: 10px; 391 | } 392 | 393 | 394 | 395 | 确认 396 | 397 | 398 | 399 | 400 | 401 | 402 | Qt::Orientation::Horizontal 403 | 404 | 405 | 406 | 40 407 | 20 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 0 425 | 0 426 | 427 | 428 | 429 | font: 700 11pt "Microsoft YaHei UI"; 430 | border:none; 431 | 432 | 433 | 修改密码 434 | 435 | 436 | Qt::AlignmentFlag::AlignCenter 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 0 445 | 15 446 | 447 | 448 | 449 | 450 | 20 451 | 20 452 | 453 | 454 | 455 | 456 | 20 457 | 20 458 | 459 | 460 | 461 | QPushButton { 462 | border: none; 463 | background: transparent; 464 | color: rgb(78, 78, 78); 465 | font: 16pt 'Microsoft New Tai Lue'; 466 | } 467 | 468 | QPushButton:hover { 469 | border: none; 470 | background: transparent; 471 | color: white; 472 | font: 16pt 'Microsoft New Tai Lue'; 473 | background: red; 474 | border-radius: 3px; 475 | } 476 | 477 | 478 | x 479 | 480 | 481 | false 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | LineChangePass 492 | QLineEdit 493 |
changepassword.h
494 |
495 |
496 | 497 | 498 |
499 | -------------------------------------------------------------------------------- /user/user/choicedialog.cpp: -------------------------------------------------------------------------------- 1 | #include "choicedialog.h" 2 | #include "ui_choicedialog.h" 3 | #include "autocleartextedit.h" 4 | 5 | ChoiceDialog::ChoiceDialog(QWidget *parent) 6 | : QDialog(parent) 7 | , ui(new Ui::ChoiceDialog) 8 | { 9 | ui->setupUi(this); 10 | //初始化窗口 11 | QIcon icon(":/pictures/suliao.png");//初始化窗口 12 | setWindowIcon(icon); 13 | setWindowFlags( Qt::FramelessWindowHint | Qt::Dialog); 14 | setAttribute(Qt::WA_TranslucentBackground);//允许背景透明 15 | //设置文本框 16 | setEdit(); 17 | // 连接按钮的点击信号 18 | connect(ui->but_yes, &QPushButton::clicked, this, &ChoiceDialog::reject); 19 | connect(ui->but_no, &QPushButton::clicked, this, &ChoiceDialog::accept); 20 | // 将窗口居中显示 21 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 22 | if (topLevelParent) { 23 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 24 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 25 | move(x, y); 26 | } 27 | } 28 | 29 | 30 | ChoiceDialog::~ChoiceDialog() 31 | { 32 | delete ui; 33 | } 34 | 35 | 36 | void ChoiceDialog::setEdit()//设置文本框 37 | { 38 | ui->textEdit_notice->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用垂直滚动条 39 | ui->textEdit_notice->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用水平滚动条 40 | ui->textEdit_notice->setReadOnly(true);//设置为只读 41 | ui->textEdit_notice->setAlignment(Qt::AlignCenter); 42 | } 43 | 44 | 45 | void ChoiceDialog::paintEvent(QPaintEvent *event)//窗口背景 46 | { 47 | //调用基类方法以处理父类的绘图 48 | QDialog::paintEvent(event); 49 | QPainter painter(this); 50 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 51 | //设置圆角半径 52 | int radius = 4;//圆角半径 53 | //设置背景颜色 54 | painter.setBrush(QBrush(QColor(255, 255, 255))); 55 | //绘制圆角矩形背景 56 | painter.drawRoundedRect(rect(), radius, radius); 57 | } 58 | 59 | 60 | void ChoiceDialog::transText(QString text)//改变文字 61 | { 62 | //设置 textEdit_notice 的文本 63 | ui->textEdit_notice->setText(text); 64 | ui->textEdit_notice->setAlignment(Qt::AlignCenter); 65 | } 66 | 67 | 68 | void ChoiceDialog::transButText(QString no, QString yes)//改变按钮文字 69 | { 70 | ui->but_no->setText(no); 71 | ui->but_yes->setText(yes); 72 | } 73 | 74 | 75 | void ChoiceDialog::on_but_yes_clicked()//确认 76 | { 77 | close(); 78 | } 79 | 80 | 81 | void ChoiceDialog::on_but_no_clicked()//取消 82 | { 83 | close(); 84 | } 85 | 86 | -------------------------------------------------------------------------------- /user/user/choicedialog.h: -------------------------------------------------------------------------------- 1 | #ifndef CHOICEDIALOG_H 2 | #define CHOICEDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ui { 9 | class ChoiceDialog; 10 | } 11 | 12 | class ChoiceDialog : public QDialog 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit ChoiceDialog(QWidget *parent = nullptr); 18 | ~ChoiceDialog(); 19 | void setEdit();//设置文本框 20 | void paintEvent(QPaintEvent *event);//窗口背景 21 | void transText(QString text);//改变文字 22 | void transButText(QString no, QString yes);//改变按钮文字 23 | 24 | private slots: 25 | void on_but_yes_clicked();//确认 26 | void on_but_no_clicked();//取消 27 | 28 | private: 29 | Ui::ChoiceDialog *ui; 30 | }; 31 | 32 | #endif // CHOICEDIALOG_H 33 | -------------------------------------------------------------------------------- /user/user/choicedialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ChoiceDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 247 10 | 142 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 20 | Qt::ContextMenuPolicy::NoContextMenu 21 | 22 | 23 | border:none; 24 | font: 12pt "Microsoft YaHei UI"; 25 | padding:5px; 26 | background:transparent; 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0 35 | 0 36 | 37 | 38 | 39 | 40 | 0 41 | 30 42 | 43 | 44 | 45 | PointingHandCursor 46 | 47 | 48 | Qt::ContextMenuPolicy::NoContextMenu 49 | 50 | 51 | QPushButton { 52 | font: 13pt 'Microsoft YaHei UI'; 53 | background-color: rgb(238, 238, 238); 54 | color: black; 55 | border:none; 56 | border-radius: 5px; 57 | } 58 | QPushButton:hover { 59 | background-color: rgb(225, 225, 225); 60 | color: red; 61 | border-radius: 5px; 62 | } 63 | QPushButton:pressed { 64 | background-color: rgb(206, 206, 206); 65 | color: red; 66 | border-radius: 5px; 67 | } 68 | 69 | 70 | 确定 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 0 79 | 0 80 | 81 | 82 | 83 | 84 | 0 85 | 30 86 | 87 | 88 | 89 | PointingHandCursor 90 | 91 | 92 | Qt::ContextMenuPolicy::NoContextMenu 93 | 94 | 95 | QPushButton { 96 | font: 13pt 'Microsoft YaHei UI'; 97 | background-color: rgb(238, 238, 238); 98 | color: black; 99 | border:none; 100 | border-radius: 5px; 101 | } 102 | QPushButton:hover { 103 | background-color: rgb(225, 225, 225); 104 | color: black; 105 | border-radius: 5px; 106 | } 107 | QPushButton:pressed { 108 | background-color: rgb(206, 206, 206); 109 | color: black; 110 | border-radius: 5px; 111 | } 112 | 113 | 114 | 取消 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | AutoClearTextEdit 123 | QTextEdit 124 |
autocleartextedit.h
125 |
126 |
127 | 128 | 129 |
130 | -------------------------------------------------------------------------------- /user/user/cutavator.cpp: -------------------------------------------------------------------------------- 1 | #include "cutavator.h" 2 | #include "ui_cutavator.h" 3 | #include "registerwindow.h" 4 | 5 | CutAvator::CutAvator(const QString &mypath,QWidget *parent) 6 | : QDialog(parent),ui(new Ui::CutAvator) 7 | , path(mypath) 8 | { 9 | ui->setupUi(this); 10 | //处理传入的图片,确保它是有效的 11 | dealImage(mypath); 12 | //先截一次 防止图片格式出错 13 | on_but_cut_clicked(); 14 | //连接截取框信号槽 15 | connect(ui->lab_cut, &DraggableResizableLabel::labelMoved, this, &CutAvator::moveRect); 16 | ui->lab_cut->resize(277,277); 17 | // 将窗口居中显示 18 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 19 | if (topLevelParent) { 20 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 21 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 22 | move(x, y); 23 | } 24 | } 25 | 26 | 27 | CutAvator::~CutAvator() 28 | { 29 | delete ui; 30 | delete labelRect; 31 | } 32 | 33 | 34 | void CutAvator::dealImage(QString path)//处理传入的图片 35 | { 36 | QImage image(path); 37 | if (image.isNull()) { 38 | QMessageBox msgBox; 39 | QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); 40 | msgBox.setIcon(QMessageBox::Critical); 41 | msgBox.setWindowIcon(icon); 42 | msgBox.setWindowTitle("加载失败"); 43 | msgBox.setText("您的图片有问题!"); 44 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog); 45 | msgBox.exec(); 46 | return; 47 | } 48 | image = image.convertToFormat(QImage::Format_ARGB32);//避免透明度问题 49 | path = "saved_background_image.png"; 50 | image.save(path, "PNG");//保存为PNG格式 51 | setBackground(path); 52 | } 53 | 54 | 55 | void CutAvator::paintEvent(QPaintEvent *event)//初始化整个窗口背景 56 | { 57 | QPainter painter(this); 58 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 59 | QPixmap pixmap(":/pictures/094 Cloudy Apple - trans.png"); 60 | painter.drawPixmap(0, 0, width(), height(), pixmap); 61 | QIcon icon(":/pictures/suliao.png"); 62 | setWindowIcon(icon); 63 | } 64 | 65 | 66 | void CutAvator::setBackground(QString avapath)//设置头像 67 | { 68 | QPixmap originalPixMap(avapath); 69 | QSize targetSize(277, 300);//子窗口大小 70 | QSize maxSize(277, 277);//最大图片尺寸 71 | QPixmap scaledPixMap = originalPixMap.scaled(maxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); 72 | QPixmap resultPixMap(targetSize); 73 | QPainter painter(&resultPixMap); 74 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 75 | painter.fillRect(resultPixMap.rect(), QColor(255, 255, 255, 255));//背景为白色 76 | //计算居中绘制位置 77 | int x = (targetSize.width() - scaledPixMap.width()) / 2; 78 | int y = (targetSize.height() - scaledPixMap.height()) / 2 + 11.5; 79 | painter.drawPixmap(x, y, scaledPixMap); 80 | //计算 labelRect 的位置 81 | if (flag > 0) { 82 | delete labelRect; 83 | labelRect = nullptr; 84 | flag--; 85 | } 86 | CutAvator::labelRect = new QRect(ui->lab_cut->geometry()); 87 | flag++; 88 | //计算全局位置 89 | QPoint globalPos = ui->lab_cut->mapToGlobal(QPoint(0, 0)) + QPoint(0, 23); 90 | labelRect->moveTopLeft(globalPos); 91 | //保存 labelRect 区域的背景 92 | QPixmap backgroundPixmap(resultPixMap.copy(*labelRect)); 93 | //绘制半透明层 94 | painter.fillRect(resultPixMap.rect(), QColor(0, 0, 0, 128)); 95 | //在矩形区域内恢复背景 96 | painter.drawPixmap(labelRect->topLeft(), backgroundPixmap); 97 | //绘制 labelRect 边框 98 | painter.setPen(QColor(0, 0, 0));//黑色边框 99 | painter.drawRect(*labelRect); 100 | //设置调色板应用背景图 101 | QPalette palette; 102 | palette.setBrush(QPalette::Window, resultPixMap); 103 | ui->dock_avator->setAutoFillBackground(true); 104 | ui->dock_avator->setPalette(palette); 105 | ui->dock_avator->setFeatures(QDockWidget::NoDockWidgetFeatures); 106 | } 107 | 108 | 109 | void CutAvator::moveRect(const QPoint &newPosition)//移动明亮矩形更新头像 110 | { 111 | QSize targetSize(277, 300);//子窗口大小 112 | QSize maxSize(277, 277);//最大图片尺寸 113 | QPixmap originalPixMap(path); 114 | QPixmap scaledPixMap = originalPixMap.scaled(maxSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); 115 | QPixmap resultPixMap(targetSize); 116 | QPainter painter(&resultPixMap); 117 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 118 | painter.fillRect(resultPixMap.rect(), QColor(255, 255, 255, 255));//背景为白色 119 | //更新 labelRect 的大小以匹配 ui->lab_cut 120 | QSize newSize = ui->lab_cut->size(); 121 | labelRect->setSize(newSize); 122 | labelRect->moveTopLeft(newPosition + QPoint(0, 23)); 123 | //计算居中绘制位置 124 | int x = (targetSize.width() - scaledPixMap.width()) / 2; 125 | int y = (targetSize.height() - scaledPixMap.height()) / 2 + 11.5; 126 | painter.drawPixmap(x, y, scaledPixMap); 127 | //保存 labelRect 区域的背景 128 | QPixmap backgroundPixmap(resultPixMap.copy(*labelRect)); 129 | //绘制半透明层 130 | painter.fillRect(resultPixMap.rect(), QColor(0, 0, 0, 128)); 131 | //在矩形区域内恢复背景 132 | painter.drawPixmap(labelRect->topLeft(), backgroundPixmap); 133 | //绘制 labelRect 边框 134 | painter.setPen(QColor(0, 0, 0, 0));//黑色边框 135 | painter.drawRect(*labelRect); 136 | //更新调色板以使用新的背景图像 137 | QPalette palette; 138 | palette.setBrush(QPalette::Window, resultPixMap); 139 | ui->dock_avator->setPalette(palette); 140 | } 141 | 142 | 143 | void CutAvator::on_but_cut_clicked()//点击后剪裁头像 144 | { 145 | ui->lab_cut->setVisible(false);//防止截到边框黑边 146 | //获取dock窗口的背景并拉伸 147 | QPixmap dockPixmap = ui->dock_avator->grab(); 148 | QPixmap dockPixmapResize = dockPixmap.scaled(277, 300, 149 | Qt::KeepAspectRatio, Qt::SmoothTransformation); 150 | //获取 lab_cut 在 dock_avator 中的位置和大小 151 | QRect cutrect = ui->lab_cut->geometry();//获取位置和大小 152 | QPoint cutPosInDock = ui->lab_cut->mapTo(ui->dock_avator, QPoint(0, 0)); 153 | cutrect.moveTo(cutPosInDock);//移动到 dock_avator 的坐标 154 | //确保 cutrect 在 dockpixmap_resize 内 155 | cutrect.intersects(QRect(0, 0, dockPixmapResize.width(), dockPixmapResize.height())); 156 | //从调整大小后的 dockpixmap 中复制对应的区域 157 | QPixmap finalpixmap = dockPixmapResize.copy(cutrect); 158 | finalpixmap.save("saved_background_image.png", "PNG"); 159 | path = "saved_background_image.png"; 160 | moveRect(ui->lab_cut->mapToParent(QPoint(0, 0))); 161 | ui->lab_cut->setVisible(true); 162 | } 163 | 164 | 165 | void CutAvator::on_but_yes_clicked()//上传头像并关闭窗口 166 | { 167 | emit cutOk(path); 168 | close(); 169 | } 170 | 171 | 172 | void DraggableResizableLabel::mousePressEvent(QMouseEvent *event)//点击判断是要干什么 173 | { 174 | if (event->button() == Qt::LeftButton) 175 | { 176 | myOffset = event->pos(); 177 | myResizing = (event->pos().x() > width() - 10 && event->pos().y() > height() - 10); 178 | } 179 | } 180 | 181 | 182 | void DraggableResizableLabel::mouseMoveEvent(QMouseEvent *event)//移动时判断是移动还是变动大小 183 | { 184 | //检测鼠标是否在右下角区域 185 | if (event->pos().x() > width() - 10 && event->pos().y() > height() - 10) 186 | { 187 | setCursor(Qt::SizeFDiagCursor);//设置光标为调整大小 188 | myResizing = true; 189 | } 190 | else 191 | { 192 | setCursor(Qt::ArrowCursor);//设置光标为箭头 193 | myResizing = false; 194 | } 195 | if (event->buttons() & Qt::LeftButton) 196 | { 197 | if (myResizing) 198 | { 199 | //调整大小,保持正方形 200 | int newSize = qMax(50, qMin(event->pos().x(), event->pos().y())); 201 | QRect parentRect = parentWidget()->rect(); 202 | //确保新大小不超出父窗口的尺寸 203 | int maxWidth = parentRect.width() - pos().x(); 204 | int maxHeight = parentRect.height() - pos().y(); 205 | newSize = qMin(newSize, qMin(maxWidth, maxHeight)); 206 | setFixedSize(newSize, newSize); 207 | emit labelMoved(mapToParent(QPoint(0, 0)));//发送当前标签的位置 208 | } 209 | else 210 | { 211 | //移动标签 212 | QPoint newPosition = mapToParent(event->pos() - myOffset); 213 | //限制移动范围,确保不超出父窗口 214 | QRect parentRect = parentWidget()->rect(); 215 | QSize labelSize = size(); 216 | newPosition.setX(qMax(parentRect.left(), qMin(newPosition.x(), parentRect.right() - labelSize.width()))); 217 | newPosition.setY(qMax(parentRect.top(), qMin(newPosition.y(), parentRect.bottom() - labelSize.height()))); 218 | 219 | move(newPosition); 220 | emit labelMoved(newPosition);//发送新位置 221 | } 222 | } 223 | } 224 | 225 | 226 | void DraggableResizableLabel::mouseReleaseEvent(QMouseEvent *event)//释放重置状态 227 | { 228 | Q_UNUSED(event); 229 | myResizing = false;//重置状态 230 | unsetCursor();//恢复光标 231 | } 232 | 233 | -------------------------------------------------------------------------------- /user/user/cutavator.h: -------------------------------------------------------------------------------- 1 | #ifndef CUTAVATOR_H 2 | #define CUTAVATOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Ui { 18 | class CutAvator; 19 | } 20 | 21 | 22 | class CutAvator : public QDialog 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | explicit CutAvator(const QString &mypath,QWidget *parent = nullptr); 28 | ~CutAvator(); 29 | void dealImage(QString path);//处理传入的图片 30 | void paintEvent(QPaintEvent *event);//初始化整个窗口背景 31 | void setBackground(QString avapath);//设置头像 32 | 33 | public slots: 34 | void moveRect(const QPoint &newPosition);//移动明亮矩形更新头像 35 | 36 | signals: 37 | void cutOk(const QPixmap &pixmap);//裁剪完了发送信号 38 | 39 | private slots: 40 | void on_but_cut_clicked();//点击后剪裁头像 41 | void on_but_yes_clicked();//点击后上传头像并关闭窗口 42 | 43 | private: 44 | Ui::CutAvator *ui; 45 | QString path; 46 | QRect *labelRect; 47 | QPainter painter; 48 | int flag = 0; 49 | }; 50 | 51 | class DraggableResizableLabel : public QLabel 52 | { 53 | Q_OBJECT 54 | public: 55 | explicit DraggableResizableLabel(QWidget *parent = nullptr) : QLabel(parent) 56 | {} 57 | 58 | signals: 59 | void labelMoved(const QPoint &newPosition);//标签发生任何变化时发送信号 60 | 61 | protected: 62 | void mousePressEvent(QMouseEvent *event) override;//点击判断是要干什么 63 | void mouseMoveEvent(QMouseEvent *event) override;//移动时判断是移动还是变动大小 64 | void mouseReleaseEvent(QMouseEvent *event) override;//释放重置状态 65 | 66 | private: 67 | QPoint myOffset; 68 | bool myResizing = false;//标志是否正在调整大小 69 | }; 70 | 71 | #endif // CUTAVATOR_H 72 | -------------------------------------------------------------------------------- /user/user/cutavator.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CutAvator 4 | 5 | 6 | 7 | 0 8 | 0 9 | 394 10 | 376 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 311 22 | 311 23 | 24 | 25 | 26 | 27 | 900 28 | 900 29 | 30 | 31 | 32 | Qt::ContextMenuPolicy::NoContextMenu 33 | 34 | 35 | 编辑头像 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Qt::Orientation::Horizontal 44 | 45 | 46 | 47 | 40 48 | 20 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 0 58 | 0 59 | 60 | 61 | 62 | 63 | 80 64 | 30 65 | 66 | 67 | 68 | PointingHandCursor 69 | 70 | 71 | Qt::ContextMenuPolicy::NoContextMenu 72 | 73 | 74 | QPushButton { 75 | font: 12pt 'Microsoft YaHei UI'; 76 | background-color: rgb(5, 186, 251); 77 | color: white; 78 | border-radius: 10px; 79 | } 80 | 81 | QPushButton:hover { 82 | background-color: rgba(5, 186, 251, 0.7); 83 | color: white; 84 | border-radius: 10px; 85 | } 86 | 87 | QPushButton:pressed { 88 | background-color: rgba(0, 123, 255, 0.8); 89 | color: rgba(255, 255, 255, 0.9); 90 | border-radius: 10px; 91 | } 92 | 93 | 94 | 裁剪 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 0 103 | 0 104 | 105 | 106 | 107 | 108 | 80 109 | 30 110 | 111 | 112 | 113 | PointingHandCursor 114 | 115 | 116 | Qt::ContextMenuPolicy::NoContextMenu 117 | 118 | 119 | QPushButton { 120 | font: 12pt 'Microsoft YaHei UI'; 121 | background-color: rgb(5, 186, 251); 122 | color: white; 123 | border-radius: 10px; 124 | } 125 | 126 | QPushButton:hover { 127 | background-color: rgba(5, 186, 251, 0.7); 128 | color: white; 129 | border-radius: 10px; 130 | } 131 | 132 | QPushButton:pressed { 133 | background-color: rgba(0, 123, 255, 0.8); 134 | color: rgba(255, 255, 255, 0.9); 135 | border-radius: 10px; 136 | } 137 | 138 | 139 | 确认 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 0 150 | 0 151 | 152 | 153 | 154 | 155 | 277 156 | 300 157 | 158 | 159 | 160 | 161 | 277 162 | 300 163 | 164 | 165 | 166 | QDockWidget::title { 167 | background: rgb(241, 231, 234) 168 | } 169 | 170 | 171 | 172 | 173 | 174 | 0 175 | 0 176 | 277 177 | 283 178 | 179 | 180 | 181 | border: 2px dashed rgb(0, 0, 0); 182 | color:rgb(0, 0, 127); 183 | 184 | 185 | 186 | 187 | 188 | 189 | Qt::AlignmentFlag::AlignCenter 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | DraggableResizableLabel 200 | QLabel 201 |
cutavator.h
202 |
203 |
204 | 205 | but_yes 206 | 207 | 208 | 209 |
210 | -------------------------------------------------------------------------------- /user/user/dialog.cpp: -------------------------------------------------------------------------------- 1 | #include "dialog.h" 2 | #include "ui_dialog.h" 3 | #include "autocleartextedit.h" 4 | 5 | Dialog::Dialog(QWidget *parent) 6 | : QDialog(parent) 7 | , ui(new Ui::Dialog) 8 | { 9 | ui->setupUi(this); 10 | //初始化窗口 11 | QIcon icon(":/pictures/suliao.png");//初始化窗口 12 | setWindowIcon(icon); 13 | setWindowFlags( Qt::FramelessWindowHint | Qt::Dialog); 14 | setAttribute(Qt::WA_TranslucentBackground);//允许背景透明 15 | //设置文本框 16 | setEdit(); 17 | // 将窗口居中显示 18 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 19 | if (topLevelParent) { 20 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 21 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 22 | move(x, y); 23 | } 24 | } 25 | 26 | 27 | Dialog::~Dialog() 28 | { 29 | delete ui; 30 | } 31 | 32 | 33 | void Dialog::setEdit()//设置文本框 34 | { 35 | ui->textEdit_notice->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用垂直滚动条 36 | ui->textEdit_notice->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//禁用水平滚动条 37 | ui->textEdit_notice->setReadOnly(true);//设置为只读 38 | ui->textEdit_notice->setAlignment(Qt::AlignCenter); 39 | } 40 | 41 | 42 | void Dialog::paintEvent(QPaintEvent *event)//窗口背景 43 | { 44 | //调用基类方法以处理父类的绘图 45 | QDialog::paintEvent(event); 46 | QPainter painter(this); 47 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 48 | //设置圆角半径 49 | int radius = 4;//圆角半径 50 | //设置背景颜色 51 | painter.setBrush(QBrush(QColor(255, 255, 255))); 52 | //绘制圆角矩形背景 53 | painter.drawRoundedRect(rect(), radius, radius); 54 | } 55 | 56 | 57 | void Dialog::transText(QString text)//改变文字 58 | { 59 | //设置 textEdit_notice 的文本 60 | ui->textEdit_notice->setText(text); 61 | ui->textEdit_notice->setAlignment(Qt::AlignCenter); 62 | } 63 | 64 | 65 | void Dialog::on_but_delete_clicked()//点击确定关闭窗口 66 | { 67 | this->close(); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /user/user/dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef DIALOG_H 2 | #define DIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ui { 9 | class Dialog; 10 | } 11 | 12 | 13 | class Dialog : public QDialog 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit Dialog(QWidget *parent = nullptr); 19 | ~Dialog(); 20 | void setEdit();//设置文本框 21 | void paintEvent(QPaintEvent *event);//窗口背景 22 | void transText(QString text);//改变文字 23 | 24 | private slots: 25 | void on_but_delete_clicked();//点击确定关闭窗口 26 | 27 | private: 28 | Ui::Dialog *ui; 29 | }; 30 | 31 | #endif // DIALOG_H 32 | -------------------------------------------------------------------------------- /user/user/dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | Qt::WindowModality::WindowModal 7 | 8 | 9 | 10 | 0 11 | 0 12 | 250 13 | 140 14 | 15 | 16 | 17 | Dialog 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Qt::Orientation::Horizontal 26 | 27 | 28 | QSizePolicy::Policy::Fixed 29 | 30 | 31 | 32 | 50 33 | 20 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 0 43 | 0 44 | 45 | 46 | 47 | 48 | 0 49 | 30 50 | 51 | 52 | 53 | PointingHandCursor 54 | 55 | 56 | Qt::ContextMenuPolicy::NoContextMenu 57 | 58 | 59 | QPushButton { 60 | font: 13pt 'Microsoft YaHei UI'; 61 | background-color: rgb(238, 238, 238); 62 | color: black; 63 | border:none; 64 | border-radius: 5px; 65 | } 66 | QPushButton:hover { 67 | background-color: rgb(225, 225, 225); 68 | color: black; 69 | border-radius: 5px; 70 | } 71 | QPushButton:pressed { 72 | background-color: rgb(206, 206, 206); 73 | color: black; 74 | border-radius: 5px; 75 | } 76 | 77 | 78 | 确定 79 | 80 | 81 | 82 | 83 | 84 | 85 | Qt::Orientation::Horizontal 86 | 87 | 88 | QSizePolicy::Policy::Fixed 89 | 90 | 91 | 92 | 50 93 | 20 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | Qt::Orientation::Horizontal 106 | 107 | 108 | 109 | 13 110 | 87 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | Qt::ContextMenuPolicy::NoContextMenu 119 | 120 | 121 | border:none; 122 | font: 12pt "Microsoft YaHei UI"; 123 | padding:5px; 124 | background:transparent; 125 | 126 | 127 | 128 | 129 | 130 | 131 | Qt::Orientation::Horizontal 132 | 133 | 134 | 135 | 13 136 | 87 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | AutoClearTextEdit 148 | QTextEdit 149 |
autocleartextedit.h
150 |
151 |
152 | 153 | 154 |
155 | -------------------------------------------------------------------------------- /user/user/findpassword.cpp: -------------------------------------------------------------------------------- 1 | #include "findpassword.h" 2 | #include "qevent.h" 3 | #include "ui_findpassword.h" 4 | #include "dialog.h" 5 | 6 | FindPassword::FindPassword(QTcpSocket* msocket,QWidget *parent) 7 | : QMainWindow(parent) 8 | , ui(new Ui::FindPassword),socket(msocket) 9 | { 10 | ui->setupUi(this); 11 | //初始化窗口 12 | setWindowFlags(Qt::Dialog); 13 | //给输入框设置验证器 14 | setVal(); 15 | // 将窗口居中显示 16 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 17 | if (topLevelParent) { 18 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 19 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 20 | move(x, y); 21 | } 22 | } 23 | 24 | 25 | FindPassword::~FindPassword() 26 | { 27 | delete ui; 28 | delete validator; 29 | } 30 | 31 | 32 | void FindPassword::setVal()//给输入框设置验证器 33 | { 34 | QRegularExpression regExp("^[a-zA-Z0-9]{1,12}$"); 35 | FindPassword::validator = new QRegularExpressionValidator(regExp, this); 36 | ui->line_pages1->setValidator(validator); 37 | ui->line_pages3->setValidator(validator); 38 | ui->line_pages3_2->setValidator(validator); 39 | } 40 | 41 | 42 | void FindPassword::paintEvent(QPaintEvent *event)//初始化背景 43 | { 44 | QPainter painter(this); 45 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 46 | QPixmap pixmap(":/pictures/094 Cloudy Apple - trans.png"); 47 | painter.drawPixmap(0, 0, width(), height(), pixmap); 48 | } 49 | 50 | 51 | void FindPassword::closeEvent(QCloseEvent *event)//关闭窗口事件 52 | { 53 | this->disconnect(); 54 | //在关闭时调用 deleteLater 55 | this->deleteLater(); 56 | //接受关闭事件 57 | event->accept(); 58 | } 59 | 60 | 61 | void FindPassword::mousePressEvent(QMouseEvent *event)//点击窗口空白让所有输入框失去焦点 62 | { 63 | ui->line_pages1->clearFocus(); 64 | ui->line_pages2->clearFocus(); 65 | ui->line_pages3->clearFocus(); 66 | ui->line_pages3_2->clearFocus(); 67 | } 68 | 69 | 70 | void FindPassword::on_but_pages1_clicked()//切换页面 71 | { 72 | if(socket->state() != QAbstractSocket::ConnectedState){//没连接到服务器 73 | Dialog msgBox(this); 74 | msgBox.transText("请检查您的网络连接!"); 75 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 76 | msgBox.exec(); 77 | return; 78 | } 79 | jsonObj = QJsonObject(); 80 | jsonObj["tag"] = "findpassword1"; 81 | jsonObj["qq_number"] = ui->line_pages1->text(); 82 | //发送消息 83 | jsonDoc = QJsonDocument(jsonObj); 84 | jsonData = jsonDoc.toJson(); 85 | //添加标识符 86 | QByteArray messageWithSeparator = jsonData + "END"; 87 | //发送JSON 数据 88 | socket->write(messageWithSeparator); 89 | socket->flush(); 90 | jsonData.clear(); 91 | qDebug() << "发送要找回的账号了"; 92 | } 93 | 94 | 95 | void FindPassword::on_but_pages2_clicked()//切换页面 96 | { 97 | if(socket->state() != QAbstractSocket::ConnectedState){//没连接到服务器 98 | Dialog msgBox(this); 99 | msgBox.transText("请检查您的网络连接!"); 100 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 101 | msgBox.exec(); 102 | return; 103 | } 104 | jsonObj = QJsonObject(); 105 | jsonObj["tag"] = "findpassword2"; 106 | jsonObj["qq_number"] = ui->line_pages1->text(); 107 | jsonObj["theanswer"] = ui->line_pages2->text(); 108 | //发送消息 109 | jsonDoc = QJsonDocument(jsonObj); 110 | jsonData = jsonDoc.toJson(); 111 | //添加标识符 112 | QByteArray messageWithSeparator = jsonData + "END"; 113 | //发送JSON 数据 114 | socket->write(messageWithSeparator); 115 | socket->flush(); 116 | jsonData.clear(); 117 | qDebug() << "发送密保答案了"<state() != QAbstractSocket::ConnectedState){//没连接到服务器 124 | Dialog msgBox(this); 125 | msgBox.transText("请检查您的网络连接!"); 126 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 127 | msgBox.exec(); 128 | return; 129 | } 130 | if(ui->line_pages3->text() != ui->line_pages3_2->text()){ 131 | Dialog msgBox(this); 132 | msgBox.transText("您的两次密码不一致!"); 133 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 134 | msgBox.exec(); 135 | return; 136 | } 137 | jsonObj = QJsonObject(); 138 | jsonObj["tag"] = "findpassword3"; 139 | jsonObj["qq_number"]= ui->line_pages1->text(); 140 | jsonObj["password"] = ui->line_pages3_2->text(); 141 | //发送消息 142 | jsonDoc = QJsonDocument(jsonObj); 143 | jsonData = jsonDoc.toJson(); 144 | //添加标识符 145 | QByteArray messageWithSeparator = jsonData + "END"; 146 | //发送JSON 数据 147 | socket->write(messageWithSeparator); 148 | socket->flush(); 149 | jsonData.clear(); 150 | qDebug() << "发送修改后的密码了"<page_find->setCurrentIndex(1); 164 | ui->lab_pages2->setText(jsonObj["question"].toString()); 165 | } 166 | } 167 | 168 | 169 | void FindPassword::findPassword2(const QJsonObject &jsonObj)//看看问题回答对了没有 对应切换页面或弹窗 170 | { 171 | if(jsonObj["answer"] == "no"){ 172 | Dialog msgBox(this); 173 | msgBox.transText("您的答案不正确!"); 174 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 175 | msgBox.exec(); 176 | } 177 | if(jsonObj["answer"] == "yes"){ 178 | ui->page_find->setCurrentIndex(2); 179 | } 180 | } 181 | 182 | 183 | void FindPassword::findPassword3(const QJsonObject &jsonObj)//修改密码成功没有 对应弹窗 184 | { 185 | if(jsonObj["answer"] == "no"){ 186 | Dialog msgBox(this); 187 | msgBox.transText("请求失败!"); 188 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 189 | msgBox.exec(); 190 | } 191 | if(jsonObj["answer"] == "yes"){ 192 | QString text = "找回密码成功"; 193 | Dialog* dialog = new Dialog(this); 194 | dialog->transText(text); 195 | dialog->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 196 | dialog->exec(); 197 | this->disconnect(); 198 | this->close(); 199 | } 200 | } 201 | 202 | 203 | void LineFind::focusInEvent(QFocusEvent *event)//获得焦点处理事件 204 | { 205 | if(text() == "请输入你的账号" || text() == "请输入密保答案" || text() == "请输入新的密码" || text() == "请确认密码"){ 206 | setText(""); 207 | } 208 | setStyleSheet("font: 13pt 'Microsoft YaHei UI'; " 209 | "border: 1px solid rgba(0, 0, 0, 0.3); " 210 | "border-radius: 10px; " 211 | "color: black;"); 212 | QLineEdit::focusInEvent(event); 213 | } 214 | 215 | 216 | void LineFind::focusOutEvent(QFocusEvent *event)//失去焦点处理事件 217 | { 218 | if(text() == ""){ 219 | if(objectName() == "line_pages1"){ 220 | setStyleSheet( 221 | "font: 13pt 'Microsoft YaHei UI'; " 222 | "border: 1px solid rgba(0, 0, 0, 0.3); " 223 | "border-radius: 8px; " 224 | "color: grey;" 225 | ); 226 | setText("请输入你的账号"); 227 | } 228 | else if(objectName() == "line_pages2"){ 229 | setStyleSheet( 230 | "font: 13pt 'Microsoft YaHei UI'; " 231 | "border: 1px solid rgba(0, 0, 0, 0.3); " 232 | "border-radius: 8px; " 233 | "color: grey;" 234 | ); 235 | setText("请输入密保答案"); 236 | } 237 | else if(objectName() == "line_pages3_2"){ 238 | setStyleSheet( 239 | "font: 13pt 'Microsoft YaHei UI'; " 240 | "border: 1px solid rgba(0, 0, 0, 0.3); " 241 | "border-radius: 8px; " 242 | "color: grey;" 243 | ); 244 | setText("请输入新的密码"); 245 | } 246 | else if(objectName() == "line_pages3"){ 247 | setStyleSheet( 248 | "font: 13pt 'Microsoft YaHei UI'; " 249 | "border: 1px solid rgba(0, 0, 0, 0.3); " 250 | "border-radius: 8px; " 251 | "color: grey;" 252 | ); 253 | setText("请确认密码"); 254 | } 255 | } 256 | QLineEdit::focusOutEvent(event); 257 | } 258 | -------------------------------------------------------------------------------- /user/user/findpassword.h: -------------------------------------------------------------------------------- 1 | #ifndef FINDPASSWORD_H 2 | #define FINDPASSWORD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace Ui { 19 | class FindPassword; 20 | } 21 | 22 | 23 | class FindPassword : public QMainWindow 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | explicit FindPassword(QTcpSocket* msocket,QWidget *parent = nullptr); 29 | ~FindPassword(); 30 | void setVal();//给输入框设置验证器 31 | void paintEvent(QPaintEvent *event);//初始化背景 32 | void closeEvent(QCloseEvent *event);//关闭窗口事件 33 | void mousePressEvent(QMouseEvent *event);//点击窗口空白让所有输入框失去焦点 34 | 35 | private slots: 36 | void on_but_pages1_clicked();//切换页面 37 | void on_but_pages2_clicked();//切换页面 38 | void on_but_pages3_clicked();//提交最后的修改密码请求 39 | 40 | public slots: 41 | void findPassword1(const QJsonObject &jsonObj);//看看有没有这个账号 对应切换页面或弹窗 42 | void findPassword2(const QJsonObject &jsonObj);//看看问题回答对了没有 对应切换页面或弹窗 43 | void findPassword3(const QJsonObject &jsonObj);//看看修改密码的结果 对应弹窗 44 | 45 | private: 46 | Ui::FindPassword *ui; 47 | QTcpSocket *socket; 48 | QJsonObject jsonObj; 49 | QJsonDocument jsonDoc; 50 | QByteArray jsonData; 51 | QRegularExpressionValidator *validator; 52 | }; 53 | 54 | 55 | class LineFind :public QLineEdit//输入文本框 56 | { 57 | Q_OBJECT 58 | 59 | public: 60 | LineFind(QWidget *parent = nullptr) : QLineEdit(parent) {} 61 | 62 | public slots: 63 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 64 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 65 | }; 66 | 67 | #endif // FINDPASSWORD_H 68 | -------------------------------------------------------------------------------- /user/user/friendmessage.cpp: -------------------------------------------------------------------------------- 1 | #include "friendmessage.h" 2 | #include "ui_friendmessage.h" 3 | 4 | FriendMessage::FriendMessage(FriendInfo info, QWidget *parent) 5 | :QDialog(parent), ui(new Ui::FriendMessage) 6 | , friendInfo(info) 7 | { 8 | ui->setupUi(this); 9 | //初始化窗口 10 | QIcon icon(":/pictures/suliao.png"); 11 | setWindowIcon(icon); 12 | setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); 13 | setAttribute(Qt::WA_TranslucentBackground); 14 | //设置当前页面各信息 15 | setMessage(friendInfo); 16 | // 将窗口居中显示 17 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 18 | if (topLevelParent) { 19 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 20 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 21 | move(x, y); 22 | } 23 | } 24 | 25 | 26 | FriendMessage::~FriendMessage() 27 | { 28 | delete ui; 29 | this->disconnect(); 30 | qDebug()<<"好友信息被析构"; 31 | } 32 | 33 | 34 | void FriendMessage::paintEvent(QPaintEvent *event)//窗口背景 35 | { 36 | //调用基类方法以处理父类的绘图 37 | QDialog::paintEvent(event); 38 | QPainter painter(this); 39 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 40 | //加载背景图片 41 | QPixmap background(":/pictures/094 Cloudy Apple - trans.png"); 42 | //确保图片已加载 43 | if (background.isNull()) { 44 | qWarning("背景图像加载失败"); 45 | return; 46 | } 47 | QSize newSize = QSize(this->width(), this->height()); 48 | //将背景图缩放为新的大小 49 | QPixmap scaledBackground = background.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 50 | //计算绘制的位置,保持居中 51 | int x = (this->width() - scaledBackground.width()) / 2; 52 | int y = (this->height() - scaledBackground.height()) / 2; 53 | //设置剪裁区域以适应圆角窗口 54 | int radius = 10; 55 | QPainterPath path; 56 | path.addRoundedRect(rect(), radius, radius); 57 | painter.setClipPath(path); 58 | //绘制背景图片 59 | painter.drawPixmap(x, y, scaledBackground); 60 | //绘制边框 61 | painter.setPen(QPen(Qt::gray, 3.5)); 62 | painter.drawRoundedRect(rect(), radius, radius); 63 | } 64 | 65 | 66 | void FriendMessage::mousePressEvent(QMouseEvent *event)//捕获鼠标按下事件 67 | { 68 | //清除焦点 69 | QList widgets = this->findChildren(); 70 | for (QWidget* widget : widgets) { 71 | widget->clearFocus(); 72 | } 73 | QPoint pos = event->pos(); 74 | int margin = 30; 75 | if (pos.x() <= 30 || pos.x() >= width() - 30 || 76 | pos.y() <= 30 || pos.y() >= height() - 30){//如果点击在边缘 77 | qDebug() << "点击在边缘"; 78 | moveFlag = 1; 79 | dragPosition = event->globalPosition().toPoint() - this->frameGeometry().topLeft();//记录鼠标相对于窗口的初始偏移 80 | event->accept(); 81 | } 82 | } 83 | 84 | 85 | void FriendMessage::mouseMoveEvent(QMouseEvent *event)//实现拖拽移动效果与调整大小效果 86 | { 87 | qDebug()<<"鼠标位移了"; 88 | QPoint globalPos = event->globalPosition().toPoint();//获取当前的鼠标位置 89 | QPoint delta = globalPos - (this->frameGeometry().topLeft() + dragPosition);//计算当前鼠标位置与窗口之间的相对偏移 90 | if (event->buttons() & Qt::LeftButton) { 91 | if (moveFlag == 1) { 92 | this->move(globalPos - dragPosition); 93 | event->accept(); 94 | } 95 | //更新拖动位置 96 | dragPosition = globalPos - this->frameGeometry().topLeft(); 97 | } 98 | } 99 | 100 | 101 | void FriendMessage::mouseReleaseEvent(QMouseEvent *event)//重置移动状态 102 | { 103 | moveFlag = 0; 104 | } 105 | 106 | 107 | QString FriendMessage::pixmapToBase64(const QPixmap &pixmap)//图片转换成base64格式 108 | { 109 | QImage image = pixmap.toImage(); 110 | QBuffer buffer; 111 | buffer.open(QIODevice::WriteOnly); 112 | image.save(&buffer, "PNG"); 113 | QByteArray byteArray = buffer.data(); 114 | return QString(byteArray.toBase64()); 115 | } 116 | 117 | 118 | QPixmap FriendMessage::base64ToPixmap(const QString &base64Str)//将base64转换为图片 119 | { 120 | QByteArray byteArray = QByteArray::fromBase64(base64Str.toUtf8()); 121 | QImage image; 122 | //尝试加载PNG格式 123 | if (!image.loadFromData(byteArray, "PNG")) { 124 | //如果PNG加载失败,尝试JPG格式 125 | image.loadFromData(byteArray, "JPG"); 126 | } 127 | return QPixmap::fromImage(image); 128 | } 129 | 130 | 131 | void FriendMessage::setMessage(const FriendInfo &info)//设置当前页面各信息 132 | { 133 | ui->textEdit_account->setText(info.account); 134 | ui->textEdit_nickname->setText(info.name); 135 | ui->textEdit_sig->setText(info.signature); 136 | ui->textEdit_gender->setText(info.gender); 137 | QPixmap avator = base64ToPixmap(info.avator_base64); 138 | ui->lab_avator->setScaledContents(true); 139 | ui->lab_avator->setPixmap(avator); 140 | } 141 | 142 | 143 | void FriendMessage::on_but_cancelwindow_clicked()//关闭窗口 144 | { 145 | this->close(); 146 | this->deleteLater(); 147 | } 148 | 149 | -------------------------------------------------------------------------------- /user/user/friendmessage.h: -------------------------------------------------------------------------------- 1 | #ifndef FRIENDMESSAGE_H 2 | #define FRIENDMESSAGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace Ui { 17 | class FriendMessage; 18 | } 19 | 20 | class FriendMessage : public QDialog 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | struct FriendInfo {//存储好友信息 26 | QString account; 27 | QString name; 28 | QString avator_base64; 29 | QString gender; 30 | QString signature; 31 | }; 32 | 33 | public: 34 | explicit FriendMessage(FriendInfo info, QWidget *parent = nullptr); 35 | ~FriendMessage(); 36 | void paintEvent(QPaintEvent *event);//窗口背景 37 | void mousePressEvent(QMouseEvent *event);//捕获鼠标按下事件 38 | void mouseMoveEvent(QMouseEvent *event);//实现拖拽移动效果与调整大小效果 39 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 40 | QString pixmapToBase64(const QPixmap &pixmap);//图片转换成base64格式 41 | QPixmap base64ToPixmap(const QString &base64Str);//将base64转换为图片 42 | void setMessage(const FriendInfo &info);//设置当前页面各信息 43 | 44 | private slots: 45 | void on_but_cancelwindow_clicked();//关闭窗口 46 | 47 | private: 48 | Ui::FriendMessage *ui; 49 | FriendInfo friendInfo;//存储好友信息 50 | int moveFlag = 0; 51 | QPoint dragPosition; 52 | }; 53 | 54 | #endif // FRIENDMESSAGE_H 55 | -------------------------------------------------------------------------------- /user/user/login.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGIN_H 2 | #define LOGIN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "registerwindow.h" 30 | #include "findpassword.h" 31 | #include "mainwindow.h" 32 | #include "dialog.h" 33 | 34 | QT_BEGIN_NAMESPACE 35 | namespace Ui { 36 | class Login; 37 | } 38 | QT_END_NAMESPACE 39 | 40 | 41 | class Login : public QMainWindow 42 | { 43 | Q_OBJECT 44 | 45 | public: 46 | Login(QWidget *parent = nullptr); 47 | ~Login(); 48 | void setAva();//初始化头像 49 | void setIcon();//初始化左上角图标 50 | void setVal();//设置输入验证器 51 | void setTimer();//设置一些计时器 用于动态背景与动态按钮 52 | bool tcpConnect();//连接服务器 53 | void remeberPassword();//记住密码 54 | void rememberAvator();//记住头像 55 | void ifAutoLogin();//检查自动登录设置 56 | void ifRememberPassword();//如果没有自动登录的检查是否有人记住密码 57 | void paintEvent(QPaintEvent *event);//绘制渐变背景 58 | void mouseMoveEvent(QMouseEvent *event);//拖拽移动窗口位置 59 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 60 | void saveAvator(QString avator);//保存头像 61 | void dengLuChengGong();//登录失败 62 | void dengLuShiBai();//登录失败 63 | QPixmap createCircularPixmap(const QString &imagePath);//设置一个调整好掩码的圆形头像 64 | QPixmap getRoundedPixmap(const QPixmap srcPixmap, const int radius);//获得圆角图片 65 | void closeEvent(QCloseEvent *event);//关闭窗口事件 66 | 67 | signals: 68 | void sendAvator();//通知子窗口发送头像给服务器 69 | void zhuCeShiBai();//通知子窗口注册失败 70 | void zhuCeChengGong(QString qqnum);//通知子窗口注册成功 71 | void findPass1(const QJsonObject &jsonObj);//通知子窗口找回密码 72 | void findPass2(const QJsonObject &jsonObj);//通知子窗口回答问题的结果 73 | void findPass3(const QJsonObject &jsonObj);//通知子窗口找回密码的结果 74 | void loginSucceed(const QString account);//登录成功通知main新建一个主窗口 75 | 76 | private slots: 77 | void onReadyRead();//读取服务器发送的消息 78 | void on_gologin_clicked();//点击登录发送请求 79 | void sendLogin();//发送登录信息 80 | void updateLoginText();//更新取消按钮的文本 模拟动态效果 81 | void on_line_password_returnPressed();//回车登录也会发送请求 82 | void on_line_qqnum_returnPressed();//回车登录也会发送请求 83 | void mousePressEvent(QMouseEvent *event);//点击窗口空白让输入框失去焦点 并且判断拖拽窗口 84 | void on_line_password_textChanged(const QString &arg1);//改变密码文本是否判断登录是否可点击 85 | void on_line_qqnum_textChanged(const QString &arg1);//改变登录文本是否判断登录是否可点击 86 | void on_auto_ckbox_toggled(bool checked);//勾选自动登录自动勾选记住密码 87 | void on_ckbox_remeber_toggled(bool checked);//记住密码取消勾选时 如果自动登录仍勾选 则取消 88 | void setSty();//初始设置输入框格式 89 | void on_rgs_pbt_clicked();//注册账号 90 | void on_fgt_pbt_clicked();//找回密码 91 | void updateGradient() ;//更新渐变背景 92 | void on_but_deletewindow_clicked();//关闭按钮 93 | 94 | private: 95 | Ui::Login *ui; 96 | QTcpSocket socket; 97 | QJsonObject jsonObj; 98 | QJsonDocument jsonDoc; 99 | QByteArray jsonData; 100 | QRegularExpressionValidator *validator; 101 | QSettings settings = QSettings("settings.ini", QSettings::IniFormat); 102 | /*存储 103 | / lastlogin: 上次成功登录的用户名。如果有说明则有人记住密码了 没有则说明没人记住密码 不必理会 104 | / 账号/password: 与特定用户相关联的密码。分组存储 组名是账号 105 | */ 106 | QSettings set = QSettings("set.ini", QSettings::IniFormat); 107 | /*存储 108 | / autologin: 是否启用自动登录的布尔值。 109 | / autologinuser: 自动登录的用户名。加载后去setting中找密码 110 | */ 111 | RegisterWindow* regis;//注册账号窗口对象 112 | FindPassword* finddPassword;//找回密码窗口对象 113 | QTimer *timer; 114 | QPoint dragPosition; 115 | QString saveLoginAvatorPath;//保存上次登录成功的人的头像 用来初始化界面 116 | MainWindow *mainwind; 117 | QTimer *cancelTimer; 118 | bool cancelRequested; 119 | QTimer *textUpdateTimer;//用于更新按钮文本的计时器 120 | int dotCount = 0;//用于更新文本的点计数 121 | bool loginFlag = false;//是不是正在登录 122 | int moveFlag = 0;//用于判断是否要拖动窗口 123 | int offset = 0 ;//渐变尺度; 124 | }; 125 | 126 | class LineInput :public QLineEdit//输入框类 127 | { 128 | Q_OBJECT 129 | 130 | public: 131 | LineInput(QWidget *parent = nullptr) : QLineEdit(parent) {} 132 | 133 | public slots: 134 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 135 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 136 | }; 137 | 138 | #endif // LOGIN_H 139 | -------------------------------------------------------------------------------- /user/user/logout.cpp: -------------------------------------------------------------------------------- 1 | #include "logout.h" 2 | #include "ui_logout.h" 3 | #include "dialog.h" 4 | #include "choicedialog.h" 5 | 6 | Logout::Logout(QWidget *parent) 7 | : QDialog(parent) 8 | , ui(new Ui::Logout) 9 | { 10 | ui->setupUi(this); 11 | //初始化窗口 12 | QIcon icon(":/pictures/suliao.png"); 13 | setWindowIcon(icon); 14 | setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); 15 | setAttribute(Qt::WA_TranslucentBackground); 16 | // 将窗口居中显示 17 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 18 | if (topLevelParent) { 19 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 20 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 21 | move(x, y); 22 | } 23 | } 24 | 25 | 26 | Logout::~Logout() 27 | { 28 | delete ui; 29 | } 30 | 31 | 32 | void Logout::on_but_deletewindow_clicked()//关闭窗口 33 | { 34 | this->close(); 35 | } 36 | 37 | 38 | void Logout::setVal()//设置输入验证器 39 | { 40 | QRegularExpression regExp("^[a-zA-Z0-9]{1,12}$");//给输入框设置验证器 41 | validator = new QRegularExpressionValidator(regExp, this); 42 | ui->line_account->setValidator(validator); 43 | ui->line_password->setValidator(validator); 44 | } 45 | 46 | 47 | void Logout::paintEvent(QPaintEvent *event)//窗口背景 48 | { 49 | //调用基类方法以处理父类的绘图 50 | QDialog::paintEvent(event); 51 | QPainter painter(this); 52 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 53 | //加载背景图片 54 | QPixmap background(":/pictures/094 Cloudy Apple - trans.png"); 55 | //确保图片已加载 56 | if (background.isNull()) { 57 | qWarning("背景图像加载失败"); 58 | return; 59 | } 60 | QSize newSize = QSize(this->width(), this->height()); 61 | //将背景图缩放为新的大小 62 | QPixmap scaledBackground = background.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 63 | //计算绘制的位置,保持居中 64 | int x = (this->width() - scaledBackground.width()) / 2; 65 | int y = (this->height() - scaledBackground.height()) / 2; 66 | //设置剪裁区域以适应圆角窗口 67 | int radius = 10; 68 | QPainterPath path; 69 | path.addRoundedRect(rect(), radius, radius); 70 | painter.setClipPath(path); 71 | //绘制背景图片 72 | painter.drawPixmap(x, y, scaledBackground); 73 | //绘制边框 74 | painter.setPen(QPen(Qt::gray, 3.5)); 75 | painter.drawRoundedRect(rect(), radius, radius); 76 | } 77 | 78 | 79 | void Logout::mousePressEvent(QMouseEvent *event)//捕获鼠标按下事件 80 | { 81 | //清除焦点 82 | QList widgets = this->findChildren(); 83 | for (QWidget* widget : widgets) { 84 | widget->clearFocus(); 85 | } 86 | QPoint pos = event->pos(); 87 | int margin = 30; 88 | if (pos.x() <= 30 || pos.x() >= width() - 30 || 89 | pos.y() <= 30 || pos.y() >= height() - 30){//如果点击在边缘 90 | qDebug() << "点击在边缘"; 91 | moveFlag = 1; 92 | dragPosition = event->globalPosition().toPoint() - this->frameGeometry().topLeft();//记录鼠标相对于窗口的初始偏移 93 | event->accept(); 94 | } 95 | } 96 | 97 | 98 | void Logout::mouseMoveEvent(QMouseEvent *event)//实现拖拽移动效果与调整大小效果 99 | { 100 | qDebug()<<"鼠标位移了"; 101 | QPoint globalPos = event->globalPosition().toPoint();//获取当前的鼠标位置 102 | QPoint delta = globalPos - (this->frameGeometry().topLeft() + dragPosition);//计算当前鼠标位置与窗口之间的相对偏移 103 | if (event->buttons() & Qt::LeftButton) { 104 | if (moveFlag == 1) { 105 | this->move(globalPos - dragPosition); 106 | event->accept(); 107 | } 108 | //更新拖动位置 109 | dragPosition = globalPos - this->frameGeometry().topLeft(); 110 | } 111 | } 112 | 113 | 114 | void Logout::mouseReleaseEvent(QMouseEvent *event)//重置移动状态 115 | { 116 | moveFlag = 0; 117 | } 118 | 119 | 120 | void Logout:: closeEvent(QCloseEvent *event)//关闭窗口事件 121 | { 122 | emit customClose();//this->disconnect();放在主窗口了 123 | this->deleteLater(); 124 | event->accept(); 125 | } 126 | 127 | 128 | void Logout::on_line_account_textChanged(const QString &arg1)//判断确认是否可以点击 129 | { 130 | if(ui->line_account->text() != "" && ui->line_account->text() != "请输入您的账号" 131 | && ui->line_password->text() != "" && ui->line_password->text() != "请输入您的密码"){ 132 | ui->but_yes->setEnabled(true); 133 | ui->but_yes->setStyleSheet( 134 | "QPushButton {" 135 | "font: 12pt 'Microsoft YaHei UI';" 136 | "background-color: rgb(5, 186, 251);" 137 | "color: white;" 138 | "border-radius: 10px;" 139 | "border: 0.5px solid rgb(220, 220, 220);" 140 | "}" 141 | "QPushButton:hover {" 142 | "background-color: rgba(5, 186, 251, 0.7);" 143 | "color: white;" 144 | "border-radius: 10px;" 145 | "}" 146 | "QPushButton:pressed {" 147 | "background-color: rgba(0, 123, 255, 0.8);" 148 | "color: rgba(255, 255, 255, 0.9);" 149 | "border-radius: 10px;" 150 | "}" 151 | ); 152 | } 153 | else{ 154 | ui->but_yes->setEnabled(false); 155 | ui->but_yes->setStyleSheet( 156 | "QPushButton {" 157 | "font: 12pt 'Microsoft YaHei UI';" 158 | "background-color: rgb(167, 214, 255); " 159 | "color: white;" 160 | "border-radius: 10px;" 161 | "}" 162 | ); 163 | } 164 | } 165 | 166 | 167 | void Logout::on_line_password_textChanged(const QString &arg1)//判断确认是否可以点击 168 | { 169 | if(ui->line_account->text() != "" && ui->line_account->text() != "请输入您的账号" 170 | && ui->line_password->text() != "" && ui->line_password->text() != "请输入您的密码"){ 171 | ui->but_yes->setEnabled(true); 172 | ui->but_yes->setStyleSheet( 173 | "QPushButton {" 174 | "font: 12pt 'Microsoft YaHei UI';" 175 | "background-color: rgb(5, 186, 251);" 176 | "color: white;" 177 | "border-radius: 10px;" 178 | "border: 0.5px solid rgb(220, 220, 220);" 179 | "}" 180 | "QPushButton:hover {" 181 | "background-color: rgba(5, 186, 251, 0.7);" 182 | "color: white;" 183 | "border-radius: 10px;" 184 | "}" 185 | "QPushButton:pressed {" 186 | "background-color: rgba(0, 123, 255, 0.8);" 187 | "color: rgba(255, 255, 255, 0.9);" 188 | "border-radius: 10px;" 189 | "}" 190 | ); 191 | } 192 | else{ 193 | ui->but_yes->setEnabled(false); 194 | ui->but_yes->setStyleSheet( 195 | "QPushButton {" 196 | "font: 12pt 'Microsoft YaHei UI';" 197 | "background-color: rgb(167, 214, 255); " 198 | "color: white;" 199 | "border-radius: 10px;" 200 | "}" 201 | ); 202 | } 203 | } 204 | 205 | 206 | void Logout::on_but_yes_clicked()//是否确定注销 207 | { 208 | ChoiceDialog dialog; 209 | dialog.transText("你确定永久注销此账号吗?"); 210 | dialog.transButText("取消", "确定"); 211 | int result = dialog.exec(); 212 | if(result == QDialog::Rejected){ 213 | close(); 214 | } 215 | else if(result == QDialog::Accepted){ 216 | QJsonObject json; 217 | json["tag"] = "logout"; 218 | json["account"] = ui->line_account->text(); 219 | json["password"] = ui->line_password->text(); 220 | emit logout(json); 221 | } 222 | } 223 | 224 | 225 | void Logout::logoutAnswer(const QJsonObject& json)//注销的结果 226 | { 227 | if(json["answer"] == "user_not_found"){ 228 | Dialog dialog; 229 | dialog.transText("账号或密码错误,请检查!"); 230 | dialog.exec(); 231 | } 232 | else if(json["answer"] == "fail"){ 233 | Dialog dialog; 234 | dialog.transText("注销失败!"); 235 | dialog.exec(); 236 | } 237 | } 238 | 239 | 240 | void LineLogout::focusInEvent(QFocusEvent *event)//获得焦点处理事件 241 | { 242 | if(text() == "请输入您的账号" || text() == "请输入您的密码"){ 243 | setText(""); 244 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 245 | "border: 1px solid rgba(0, 0, 0, 0.1);" 246 | "border-radius: 8px;" 247 | "padding: 5px;" 248 | "color: black;"); 249 | } 250 | if(objectName() == "line_password"){ 251 | this->setEchoMode(Password); 252 | } 253 | QLineEdit::focusInEvent(event); 254 | } 255 | 256 | 257 | void LineLogout::focusOutEvent(QFocusEvent *event)//失去焦点处理事件 258 | { 259 | if(text() == ""){ 260 | if(objectName() == "line_accont") 261 | { 262 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 263 | "border: 1px solid rgba(0, 0, 0, 0.1);" 264 | "border-radius: 8px;" 265 | "padding: 5px;" 266 | "color: grey;"); 267 | setText("请输入您的账号"); 268 | } 269 | if(objectName() == "line_password") 270 | { 271 | setStyleSheet("font: 12pt 'Microsoft YaHei UI';" 272 | "border: 1px solid rgba(0, 0, 0, 0.1);" 273 | "border-radius: 8px;" 274 | "padding: 5px;" 275 | "color: grey;"); 276 | setText("请输入您的密码"); 277 | setEchoMode(Normal); 278 | } 279 | } 280 | QLineEdit::focusOutEvent(event); 281 | } 282 | 283 | 284 | -------------------------------------------------------------------------------- /user/user/logout.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGOUT_H 2 | #define LOGOUT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Ui { 14 | class Logout; 15 | } 16 | 17 | class Logout : public QDialog//注销类 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit Logout(QWidget *parent = nullptr); 23 | ~Logout(); 24 | void setVal();//设置输入验证器 25 | void paintEvent(QPaintEvent *event);//窗口背景 26 | void mousePressEvent(QMouseEvent *event);//捕获鼠标按下事件 27 | void mouseMoveEvent(QMouseEvent *event);//实现拖拽移动效果与调整大小效果 28 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 29 | void closeEvent(QCloseEvent *event);//关闭窗口事件 30 | 31 | private slots: 32 | void on_but_deletewindow_clicked();//关闭窗口 33 | void on_line_account_textChanged(const QString &arg1);//判断确认是否可以点击 34 | void on_line_password_textChanged(const QString &arg1);//判断确认是否可以点击 35 | void on_but_yes_clicked();//是否确定注销 36 | 37 | public slots: 38 | void logoutAnswer(const QJsonObject& json);//注销的结果 39 | 40 | signals: 41 | void customClose();//发出退出的信号 42 | void logout(const QJsonObject &json);//告知主窗体发送注销申请 43 | 44 | private: 45 | Ui::Logout *ui; 46 | int moveFlag = 0; 47 | QPoint dragPosition; 48 | QValidator *validator; 49 | }; 50 | 51 | 52 | class LineLogout:public QLineEdit//输入框类 53 | { 54 | Q_OBJECT 55 | 56 | public: 57 | LineLogout(QWidget *parent = nullptr) : QLineEdit(parent) {} 58 | 59 | public slots: 60 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 61 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 62 | }; 63 | 64 | #endif // LOGOUT_H 65 | -------------------------------------------------------------------------------- /user/user/logout.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Logout 4 | 5 | 6 | 7 | 0 8 | 0 9 | 302 10 | 187 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | border:none; 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 0 27 | 0 28 | 29 | 30 | 31 | font: 700 11pt "Microsoft YaHei UI"; 32 | border:none; 33 | 34 | 35 | 注销账号 36 | 37 | 38 | Qt::AlignmentFlag::AlignCenter 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 0 47 | 15 48 | 49 | 50 | 51 | 52 | 20 53 | 20 54 | 55 | 56 | 57 | 58 | 20 59 | 20 60 | 61 | 62 | 63 | QPushButton { 64 | border: none; 65 | background: transparent; 66 | color: rgb(78, 78, 78); 67 | font: 16pt 'Microsoft New Tai Lue'; 68 | } 69 | 70 | QPushButton:hover { 71 | border: none; 72 | background: transparent; 73 | color: white; 74 | font: 16pt 'Microsoft New Tai Lue'; 75 | background: red; 76 | border-radius: 3px; 77 | } 78 | 79 | 80 | x 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 0 96 | 0 97 | 98 | 99 | 100 | 101 | 0 102 | 50 103 | 104 | 105 | 106 | font: 12pt "Microsoft YaHei UI"; 107 | border:none; 108 | color:black; 109 | 110 | 111 | 112 | 输入账号: 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 0 121 | 0 122 | 123 | 124 | 125 | 126 | 224 127 | 38 128 | 129 | 130 | 131 | 132 | 224 133 | 38 134 | 135 | 136 | 137 | Qt::FocusPolicy::ClickFocus 138 | 139 | 140 | Qt::ContextMenuPolicy::NoContextMenu 141 | 142 | 143 | font: 12pt "Microsoft YaHei UI"; 144 | border: 1px solid rgba(0, 0, 0, 0.1); 145 | border-radius: 8px; 146 | padding:5px; 147 | color:grey; 148 | 149 | 150 | 151 | 152 | 请输入您的账号 153 | 154 | 155 | 12 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 0 168 | 0 169 | 170 | 171 | 172 | 173 | 0 174 | 50 175 | 176 | 177 | 178 | font: 12pt "Microsoft YaHei UI"; 179 | border:none; 180 | color:black; 181 | 182 | 183 | 184 | 输入密码: 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 0 193 | 0 194 | 195 | 196 | 197 | 198 | 224 199 | 38 200 | 201 | 202 | 203 | 204 | 224 205 | 38 206 | 207 | 208 | 209 | Qt::FocusPolicy::ClickFocus 210 | 211 | 212 | Qt::ContextMenuPolicy::NoContextMenu 213 | 214 | 215 | font: 12pt "Microsoft YaHei UI"; 216 | border: 1px solid rgba(0, 0, 0, 0.1); 217 | border-radius: 8px; 218 | padding:5px; 219 | color:grey; 220 | 221 | 222 | 223 | 224 | 请输入您的密码 225 | 226 | 227 | 12 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | Qt::Orientation::Horizontal 239 | 240 | 241 | 242 | 40 243 | 20 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | false 252 | 253 | 254 | 255 | 0 256 | 0 257 | 258 | 259 | 260 | 261 | 175 262 | 35 263 | 264 | 265 | 266 | PointingHandCursor 267 | 268 | 269 | QPushButton { 270 | font: 12pt "Microsoft YaHei UI"; 271 | background-color: rgb(167, 214, 255); 272 | color: white; 273 | border-radius: 10px; 274 | } 275 | 276 | 277 | 278 | 确认 279 | 280 | 281 | 282 | 283 | 284 | 285 | Qt::Orientation::Horizontal 286 | 287 | 288 | 289 | 40 290 | 20 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | LineChangePass 302 | QLineEdit 303 |
changepassword.h
304 |
305 |
306 | 307 | 308 |
309 | -------------------------------------------------------------------------------- /user/user/main.cpp: -------------------------------------------------------------------------------- 1 | #include "login.h" 2 | #include "mainwindow.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | QApplication a(argc, argv); 12 | QTranslator translator; 13 | const QStringList uiLanguages = QLocale::system().uiLanguages(); 14 | for (const QString &locale : uiLanguages) { 15 | const QString baseName = "user_" + QLocale(locale).name(); 16 | if (translator.load(":/i18n/" + baseName)) { 17 | a.installTranslator(&translator); 18 | break; 19 | } 20 | } 21 | Login w; 22 | //使用std::unique_ptr管理 QTcpSocket的实例 23 | auto socket = std::make_unique(); 24 | //使用QPointer来管理 MainWindow的指针 25 | QPointer mainWind = nullptr; 26 | //连接login窗口的 loginsucceed信号到槽 27 | QObject::connect(&w, &Login::loginSucceed, [&](const QString &account) { 28 | if (!mainWind) { 29 | mainWind = new MainWindow(account); 30 | mainWind->show(); 31 | } 32 | }); 33 | w.show(); 34 | ////////////////////////////////////////////////////////////////// 35 | Login w2; 36 | //使用std::unique_ptr管理 QTcpSocket的实例 37 | auto socket2 = std::make_unique(); 38 | //使用QPointer来管理 MainWindow的指针 39 | QPointer mainWind2 = nullptr; 40 | //连接login 窗口的 loginsucceed信号到槽 41 | QObject::connect(&w2, &Login::loginSucceed, [&](const QString &account) { 42 | if (!mainWind2) { 43 | mainWind2 = new MainWindow(account); 44 | mainWind2->show(); 45 | } 46 | }); 47 | w2.show(); 48 | return a.exec(); 49 | } 50 | -------------------------------------------------------------------------------- /user/user/mainwindow-else.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW-ELSE_H 2 | #define MAINWINDOW-ELSE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | 45 | class TalkFilterProxyModel; 46 | 47 | 48 | class TalkList : public QListView//消息列表类 49 | { 50 | Q_OBJECT 51 | 52 | public: 53 | TalkList(QWidget *parent = nullptr) : QListView(parent) { 54 | } 55 | 56 | protected: 57 | void contextMenuEvent(QContextMenuEvent *event);//菜单 58 | 59 | signals: 60 | void choiceDone(const QJsonObject &json); 61 | }; 62 | 63 | 64 | class FriendList : public QListView//好友列表类 65 | { 66 | Q_OBJECT 67 | 68 | public: 69 | FriendList(QWidget *parent = nullptr) : QListView(parent) { 70 | } 71 | 72 | void mousePressEvent(QMouseEvent *event);//实现左右键都可选择 73 | }; 74 | 75 | 76 | class FriendDelegate : public QStyledItemDelegate//好友列表委托绘图类 77 | { 78 | Q_OBJECT 79 | public: 80 | FriendDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} 81 | void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;//好友列表项委托绘图 82 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;//返回尺寸 83 | QPixmap getRoundedPixmap(QPixmap srcPixmap, const int radius)const;//获得圆角图片 84 | }; 85 | 86 | 87 | class TalkDelegate : public QStyledItemDelegate//聊天列表委托绘图类 88 | { 89 | Q_OBJECT 90 | public: 91 | TalkDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} 92 | void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;//聊天列表项委托绘图 93 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;//返回尺寸 94 | QPixmap getRoundedPixmap(QPixmap srcPixmap, const int radius)const;//获得圆角图片 95 | QString displayTimeComparison(const QString ×tampStr)const;//解析时间戳 96 | }; 97 | 98 | 99 | class FilterProxyModel : public QSortFilterProxyModel//好友列表过滤代理模型 100 | { 101 | Q_OBJECT 102 | public: 103 | explicit FilterProxyModel(QObject *parent = nullptr) 104 | : QSortFilterProxyModel(parent) { 105 | } 106 | 107 | protected: 108 | bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent)const;//好友列表过滤代理模型判断是否接收 109 | }; 110 | 111 | 112 | class TalkFilterProxyModel : public QSortFilterProxyModel//聊天列表过滤代理模型 113 | { 114 | Q_OBJECT 115 | public: 116 | explicit TalkFilterProxyModel(QObject *parent = nullptr) 117 | : QSortFilterProxyModel(parent) { 118 | } 119 | 120 | protected: 121 | bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent)const;//聊天列表过滤代理模型判断是否接收 122 | }; 123 | 124 | 125 | class LineSerach :public QLineEdit//搜索框类 126 | { 127 | Q_OBJECT 128 | 129 | public: 130 | LineSerach(QWidget *parent = nullptr) : QLineEdit(parent) {} 131 | 132 | public slots: 133 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 134 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 135 | 136 | }; 137 | 138 | 139 | class LabelAva:public QLabel//实现点击头像弹出修改信息窗口 140 | { 141 | Q_OBJECT 142 | 143 | public: 144 | LabelAva(QWidget *parent=nullptr):QLabel(parent){} 145 | void mousePressEvent(QMouseEvent *event);//点击头像发出弹出修改个人信息窗口的信号 146 | 147 | signals: 148 | void changeInfo(); 149 | }; 150 | 151 | 152 | class LabelFriendAva:public QLabel//实现点击头像弹出好友信息窗口(好友申请内的) 153 | { 154 | Q_OBJECT 155 | 156 | public: 157 | LabelFriendAva(QWidget *parent=nullptr):QLabel(parent){} 158 | void mousePressEvent(QMouseEvent *event);//点击头像弹出好友个人信息 159 | }; 160 | 161 | 162 | class LabelFriendAvaInMessage:public QLabel//实现点击头像弹出好友信息窗口(消息页面内的) 163 | { 164 | Q_OBJECT 165 | 166 | public: 167 | LabelFriendAvaInMessage(QWidget *parent=nullptr):QLabel(parent){} 168 | void mousePressEvent(QMouseEvent *event);//点击头像弹出好友个人信息 169 | 170 | signals: 171 | void showMessage(); 172 | }; 173 | 174 | 175 | class CustomTextEdit : public QTextEdit//显示好友信息的edit类 176 | { 177 | public: 178 | CustomTextEdit(QWidget *parent = nullptr) : QTextEdit(parent) , background(":/pictures/andan_touming.jpg"){} 179 | QPixmap background;//背景图 180 | 181 | protected: 182 | void paintEvent(QPaintEvent *event);//右边edit的背景 183 | }; 184 | 185 | 186 | class TalkStacked : public QStackedWidget//显示聊天信息的类 187 | { 188 | public: 189 | TalkStacked(QWidget *parent = nullptr): QStackedWidget(parent), background(":/pictures/andan_touming.jpg"){}; 190 | QPixmap background;//背景图 191 | 192 | protected: 193 | void paintEvent(QPaintEvent *event);//右边edit的背景 194 | 195 | }; 196 | 197 | 198 | class ImageLabel : public QLabel//图片消息框 199 | { 200 | Q_OBJECT 201 | 202 | public: 203 | explicit ImageLabel(const QPixmap &pixmap, QWidget *parent = nullptr); 204 | 205 | protected: 206 | void mousePressEvent(QMouseEvent *event) override;//鼠标按下事件打开图片 207 | void contextMenuEvent(QContextMenuEvent *event) override;//用户右键点击时显示菜单 208 | 209 | private: 210 | QPixmap myPixmap; 211 | }; 212 | 213 | 214 | class EnterTextEdit : public QTextEdit { 215 | Q_OBJECT 216 | 217 | public: 218 | EnterTextEdit(QWidget *parent = nullptr) : QTextEdit(parent) {} 219 | 220 | protected: 221 | void keyPressEvent(QKeyEvent *event) override;//按下判断是不是回车加ctrl 222 | 223 | signals: 224 | void enterKey();//回车和ctrl键被按下 225 | }; 226 | #endif // MAINWINDOW-ELSE_H 227 | -------------------------------------------------------------------------------- /user/user/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "addfriends.h" 43 | #include "changeinformation.h" 44 | #include "changepassword.h" 45 | #include "logout.h" 46 | #include "mainwindow-else.h" 47 | 48 | 49 | class FilterProxyModel; 50 | 51 | class TalkFilterProxyModel; 52 | 53 | namespace Ui { 54 | class MainWindow; 55 | } 56 | 57 | 58 | class MainWindow : public QMainWindow//主窗口类 59 | { 60 | Q_OBJECT 61 | 62 | public: 63 | explicit MainWindow(QString accountNumber0,QWidget *parent = nullptr); 64 | ~MainWindow(); 65 | 66 | public: 67 | struct AccountInfo {//存储好友信息 68 | QString account;//账号 69 | QString name;//名称 70 | QString avator_base64;//头像的 Base64 编码字符串 71 | QString gender;//性别 72 | QString signature;//签名 73 | }; 74 | 75 | private: 76 | void initAvatar();//初始化头像 77 | void setupFriendList();//设置好友列表模型 78 | void setupTalkList();//设置聊天列表模型 79 | void setupMenu();//设置左下角按钮菜单 80 | QString pixmapToBase64(const QPixmap &pixmap);//图片转换成base64格式 81 | QPixmap base64ToPixmap(const QString &base64Str);//将base64转换为图片 82 | void positionSendButton();//设置按钮位置 83 | void paintEvent(QPaintEvent *event);//窗口背景 84 | void createUserDatabase(const QString& account);//在本地建立或初始化该用户的数据库 85 | void setupMessageList(QListWidget *list);//设置消息页面模型 86 | bool tcpConnect();//连接服务器 87 | void havelogin(const QString& account);//发送初始化请求 88 | QPixmap getRoundedPixmap(const QPixmap srcPixmap, const int radius);//获得圆角图片 89 | bool checkSocket();//检查是不是连接上服务器了 90 | bool deleteSomeoneInFriendList(const QString &account);//清理好友列表中的某个好友 91 | bool deleteSomeoneInTalkList(const QString &account);//删除聊天列表中的某个聊天 92 | bool ifTalkHaveOpened(const QString &account);//判断某个人的聊天是否已经在消息列表中了 93 | int addSomeoneToTalkList(const AccountInfo &friendMessage, QString message, QString date, QString unread);//向聊天列表加入某个好友 94 | int selectSomeoneInTalkList(const QString &account);//打开某个人的聊天框 95 | void sendMessageToFriend(const QString &account);//给某个好友发送消息 96 | bool switchPageTo(const QString &friendId);//将聊天页面切换到账号为account的页面 97 | void addMessageTo(const QWidget *page, const QString &sender, const QString &messageType, 98 | const QString &message, const QString ×tamp);//把聊天记录添加到某个聊天页面(时间传入utc时间) 99 | void addMessageToDatabase(const QString &sender,const QString &receiver, const QString &messageType,//把聊天记录添加到本地数据库 100 | const QString &message, const QString ×tamp); 101 | QPixmap& loadAvator(const QString& friendId);//获得某人头像 102 | bool printTimeOrNot(const QString& messageTime, const QString& preMessageTime, QString& result);//判断聊天时是否需要加载新的时间 103 | void checkFriendInTalk(const QString& friendId);//检查这个好友是不是已经有打开的聊天窗口了 如果没有 则打开一个 104 | void updateTalkList(const QString& friendId);//更新某人的消息列表信息 105 | void updateTalkListFree(const QString& friendId, const QString& latestMessage, const QString& timestamp);//更新某人的消息列表信息 指定更新 106 | int updateUnread(const QString& friendId);//使某人的未读消息条数加一 如果正在聊天 则返回 107 | void clearUnread(const QString& friendId);//清空某人的未读消息 108 | void liftSomebody(const QString& friendId);//把某人从消息列表提升到最上面 109 | 110 | private slots: 111 | void on_but_maxwindow_clicked();//最大化按钮 112 | void on_but_minwindow_clicked();//最小化按钮 113 | void on_but_deletewindow_clicked();//关闭按钮 114 | void on_but_minwindow2_clicked();//页面2最小化按钮 115 | void on_but_maxwindow2_clicked();//页面2的最大化按钮 116 | void on_but_deletewindow2_clicked();//页面2关闭按钮 117 | void on_but_chat_clicked();//跳转到聊天窗口页面 118 | void on_but_friends_clicked();//跳转到联系人窗口 119 | void on_edit_input_textChanged();//输入框改变内容判断能否发送消息 120 | void on_pages_currentChanged(int arg1);//页面发生改变 修改左边菜单栏图标的背景颜色 121 | void on_but_addfriends_clicked();//添加好友按钮 122 | void on_but_add0_clicked();//添加好友按钮 123 | void goSerachFriends(const QString &account);//向服务器发送搜索用户信息申请 124 | void clearEditShow2();//清理右边好友信息视图 125 | void updateEditShow2New();//更新右边好友信息视图(好友申请) 126 | void updateEditShow2Normal(const QModelIndex &index);//更新右边好友信息视图 127 | void on_line_serach2_textChanged(const QString &arg1);//搜索输入 更新好友列表视图 128 | void on_line_serach_textChanged(const QString &arg1);//搜索输入 更新聊天列表视图 129 | void deleteFriend();//删除好友 130 | void goAddFriends(const QString &friendAccount);//添加好友 131 | void changeInfo();//弹出修改个人资料窗口 132 | void listtalkChoice(const QJsonObject& json);//聊天列表的菜单选择完毕 133 | void sendMessage(const MyAccountInfo& info);//收到修改资料窗口的信号 发送信息 134 | void changePassword1(const QJsonObject &json);//收到修改密码窗口的信号 发送信息 135 | void changePassword2(const QJsonObject &json);//收到修改密码窗口的信号 发送最终的信息 136 | void goLogout(const QJsonObject &json);//收到注销窗口发送的信号 发送注销申请 137 | void rejectAddFriends(const QString &account, const QString &sender);//拒绝好友申请 138 | void acceptAddFriends(const QString &account, const QString &sender);//接受好友申请 139 | void on_but_send_clicked();//发送信息 140 | void on_but_tool1_clicked();//发送图片 141 | void on_but_tool2_clicked();//发送文件 142 | void sendDoc(const QByteArray &jsonData, const QString &filename, const QString ×tamp, const QString &receiver);//发送文件 143 | void handleSaveDone(const QString &status);//发送文件保存完毕的信号 144 | void onTalkItemCurrentChanged();//聊天页面项切换项更新消息框视图 145 | void onFriendItemCurrentChanged();//好友列表页面项切换项更新右边视图 146 | void mousePressEvent(QMouseEvent *event);//鼠标点击事件 147 | void mouseMoveEvent(QMouseEvent *event);//实现拖拽移动效果与调整大小效果与移动到边框显示不同的图标效果 148 | void mouseReleaseEvent(QMouseEvent *event);//重置移动状态 149 | void onReadyRead();//读取服务器回复数据 150 | 151 | public://读取服务器回发数据之后执行的函数 152 | void uploadAll(const QJsonObject& json);//加载好友数据(包含聊天记录 好友申请等) 153 | void uploadFriedList(const QJsonArray &friendsArray);//加载好友列表 154 | void uploadFriedRequest(const QJsonArray &friendsRequestArray);//加载好友申请 155 | void uploadListMessages(const QString& account);//加载消息列表 156 | void uploadMessages(const QString& account);//加载消息记录 157 | void uploadUnreadMessages(const QJsonArray& messagesArray);//加载未读聊天记录 158 | void deleteSucceed(const QJsonObject& json);//删除好友成功 159 | void deleteFail(const QJsonObject& json);//删除失败 160 | void sendSerach(const QJsonObject& json);//搜索好友的结果 161 | void changeMyInfo(const QJsonObject& json);//修改用户信息的结果 162 | void changePasswordAns1(const QJsonObject& json);//修改账号密码第一个申请的结果 163 | void changePasswordAns2(const QJsonObject& json);//修改账号密码第二个申请的结果 164 | void logoutAns(const QJsonObject& json);//注销的结果 165 | void dealFriendsRequest(const QJsonObject& json);//处理好友申请的结果 166 | void dealNewAddRequest(const QJsonObject& json);//接收到新的好友申请 将其加入好友申请列表 167 | void dealAddRequestPass(const QJsonObject& json);//发送的好友申请通过 将其加入好友列表 168 | void dealYouAreDeleted(const QJsonObject& json);//处理被删除好友 169 | void dealYouAreKickedOffline(const QJsonObject& json);//处理被挤下线 170 | void dealMessages(const QJsonObject& json);//处理接收到的聊天消息 171 | void dealDocument(const QJsonObject& json);//处理接收到的文件 172 | 173 | signals: 174 | void deleteDone();//删除好友操作完毕 175 | void serachResult(const QJsonObject &json);//查找账号的结果 176 | void changeResult(const QJsonObject &json);//修改用户信息的结果 177 | void changePasswordAnswer1(const QJsonObject& json);//修改账号密码第一个申请的结果 178 | void changePasswordAnswer2(const QJsonObject& json);//修改账号密码第一个申请的结果 179 | void logoutAnswer(const QJsonObject& json);//注销的结果 180 | void saveDone(QString status);//文件保存完成 发出信号弹窗 181 | 182 | private: 183 | Ui::MainWindow *ui; 184 | AccountInfo myInfo;//用户自己的信息 185 | QVector newFriendArray;//好友申请列表 186 | QHash friendHash;//以账号为索引存储好友列表 187 | QHash messageListHash;//以账号为索引存储消息列表 188 | QHash avatorHash;//存储头像 189 | QJsonObject jsonObj; 190 | QJsonDocument jsonDoc; 191 | QByteArray jsonData; 192 | QMutex mutex; 193 | QString accountNumber;//账号 194 | QPixmap defaultAva= QPixmap(":/pictures/suliao_avator_normal.jpg"); 195 | QSqlDatabase db;//用户的数据库 196 | QTcpSocket *socket; 197 | QRegularExpressionValidator *validator; 198 | QPoint dragPosition; 199 | QStandardItem *parentItem; 200 | QString deleteFriendNum; 201 | int maxFlag = 0 ;//是否窗口最大化了; 202 | int moveFlag = 0;//移动状态 203 | int addFriendsFlag = 0;//是否已经打开添加好友窗体了 204 | int changeInfoFlag = 0;//是否已经打开修改个人信息窗体了 205 | int changePassFlag = 0;//是否已经打开修改密码窗体了 206 | int logoutFlag = 0;//是否已经打开注销窗体了 207 | int resizeFlag = 0;//改变窗口大小状态 208 | int frame = 5;//模拟边框大小 209 | AddFriends* dialogAdd;//添加好友窗口 210 | ChangeInformation* dialogChangeInfo;//修改个人信息窗口 211 | ChangePassword *dialogChangePass;//修改密码窗口 212 | Logout *logout;//注销窗口 213 | QPushButton *sendButton;//发送信息按钮 214 | QPushButton *deleteButton;//删除好友按钮 215 | QVBoxLayout *newLayout;//好友列表主布局 216 | QStandardItemModel *friendModel;//好友列表项模型 217 | FilterProxyModel *filterProxyModel;//好友列表筛选模型 218 | QStandardItemModel *talkModel;//聊天列表项模型 219 | TalkFilterProxyModel *talkFilterProxyModel;//聊天列表筛选模型 220 | QStandardItemModel *messageModel;//消息页面模型 221 | QMenu *toolMenu;//左上角菜单栏 222 | }; 223 | 224 | #endif // MAINWINDOW_H 225 | -------------------------------------------------------------------------------- /user/user/registerwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "registerwindow.h" 2 | #include "ui_registerwindow.h" 3 | #include "cutavator.h" 4 | #include "dialog.h" 5 | 6 | RegisterWindow::RegisterWindow(QTcpSocket *msocket,QWidget *parent) 7 | : QMainWindow(parent) 8 | , ui(new Ui::RegisterWindow),socket(msocket) 9 | { 10 | ui->setupUi(this); 11 | //初始化窗口 12 | setWindowFlags(Qt::Dialog); 13 | //给输入框设置验证器 14 | setVal(); 15 | //设置默认头像 16 | setAva(); 17 | // 将窗口居中显示 18 | QWidget *topLevelParent = parent ? parent->window() : nullptr; 19 | if (topLevelParent) { 20 | int x = topLevelParent->x() + (topLevelParent->width() - width()) / 2; 21 | int y = topLevelParent->y() + (topLevelParent->height() - height()) / 2; 22 | move(x, y); 23 | } 24 | } 25 | 26 | 27 | RegisterWindow::~RegisterWindow() 28 | { 29 | delete ui; 30 | } 31 | 32 | 33 | void RegisterWindow::setVal()//给输入框设置验证器 34 | { 35 | QRegularExpression regExp("^[a-zA-Z0-9]{1,12}$"); 36 | RegisterWindow::validator = new QRegularExpressionValidator(regExp, this); 37 | ui->line_password->setValidator(validator); 38 | ui->line_password2->setValidator(validator); 39 | } 40 | 41 | 42 | void RegisterWindow::setAva()//设置默认头像 43 | { 44 | QPixmap pixmap(":/pictures/suliao_avator_normal.jpg");//初始化默认头像 45 | ui->lab_avator->setPixmap(pixmap); 46 | ui->lab_avator->setScaledContents(true); 47 | } 48 | 49 | 50 | QPixmap RegisterWindow::createCircularPixmap(const QString &imagePath)//给图片裁剪成圆形 51 | { 52 | QPixmap pixmap(imagePath); 53 | double width = pixmap.width(); 54 | double height = pixmap.height(); 55 | double radius = std::min(width, height) / 2; 56 | QBitmap mask(pixmap.size()); 57 | mask.fill(Qt::color0); 58 | QPainter painter(&mask); 59 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 60 | painter.setBrush(Qt::color1); 61 | double centerX = width / 2; 62 | double centerY = height / 2; 63 | painter.drawEllipse((centerX - radius)-5, (centerY - radius)-5, (2 * radius)-2, (2 * radius)-2); 64 | pixmap.setMask(mask); 65 | return pixmap; 66 | } 67 | 68 | 69 | void RegisterWindow::paintEvent(QPaintEvent *event)//初始化背景 70 | { 71 | QPainter painter(this); 72 | painter.setRenderHint(QPainter::Antialiasing);//反锯齿 73 | QPixmap pixmap(":/pictures/094 Cloudy Apple - trans.png"); 74 | painter.drawPixmap(0, 0, width(), height(), pixmap); 75 | } 76 | 77 | 78 | QPixmap RegisterWindow::getRoundedPixmap(const QPixmap srcPixmap, const float radiusRatio)//切割圆角图片 79 | { 80 | //目标图片尺寸 81 | QSize desSize = srcPixmap.size(); 82 | //新建一个目标大小的画布QPixmap 83 | QPixmap desPixMap(desSize); 84 | //填充透明色作为背景 85 | desPixMap.fill(Qt::transparent); 86 | //以QPixmap 为绘画背景进行画笔绘制 87 | QPainter painter(&desPixMap); 88 | painter.setRenderHints(QPainter::Antialiasing);//抗锯齿 89 | painter.setRenderHints(QPainter::SmoothPixmapTransform);//平滑像素图变换 90 | QPainterPath path;//绘制路径 91 | //计算圆角半径,基于图片尺寸的比例 92 | int radius = qMin(desSize.width(), desSize.height()) * radiusRatio; 93 | //绘制圆角矩形 94 | path.addRoundedRect(0, 0, desSize.width(), desSize.height(), radius, radius); 95 | //将绘制的圆角矩形路径中内容进行裁剪 96 | painter.setClipPath(path); 97 | //将图片绘制到 desPixmap 中,忽视图片比例 98 | painter.drawPixmap(0, 0, desSize.width(), desSize.height(), 99 | srcPixmap.scaled(desSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); 100 | painter.setClipping(false);//关闭裁剪 101 | return desPixMap; 102 | } 103 | 104 | 105 | void RegisterWindow::closeEvent(QCloseEvent *event)//关闭事件 106 | { 107 | this->disconnect(); 108 | //在关闭时调用 deleteLater 109 | this->deleteLater(); 110 | //接受关闭事件 111 | event->accept(); 112 | } 113 | 114 | 115 | void RegisterWindow::mousePressEvent(QMouseEvent *event)//点击窗口空白让所有输入框失去焦点 116 | { 117 | ui->line_answer->clearFocus(); 118 | ui->line_nickname->clearFocus(); 119 | ui->line_password->clearFocus(); 120 | ui->line_password2->clearFocus(); 121 | ui->line_question->clearFocus(); 122 | } 123 | 124 | 125 | void RegisterWindow::on_line_answer_textChanged(const QString &arg1)//文本改变 判断能不能提交 126 | { 127 | if(!ui->line_nickname->text().isEmpty()&&!ui->line_password->text().isEmpty()\ 128 | &&!ui->line_password2->text().isEmpty()&&!ui->line_question->text().isEmpty()\ 129 | &&!ui->line_answer->text().isEmpty()&&ui->line_nickname->text() != "请输入昵称"\ 130 | &&ui->line_password->text() !="请输入密码" &&ui->line_password2->text() != "请确认密码"\ 131 | &&ui->line_question->text() !="请输入问题" &&ui->line_answer->text() !=" 请输入答案"){ 132 | ui->submit_but->setEnabled(true); 133 | ui->submit_but->setCursor(Qt::PointingHandCursor); 134 | ui->submit_but->setStyleSheet( 135 | "QPushButton {" 136 | " font: 12pt 'Microsoft YaHei UI';" 137 | " background-color: rgb(5, 186, 251);" 138 | " color: white;" 139 | " border-radius: 15px;" 140 | "}" 141 | "QPushButton:hover {" 142 | " background-color: rgba(5, 186, 251, 0.7);" 143 | " color: white;" 144 | " border-radius: 15px;" 145 | "}" 146 | "QPushButton:pressed {" 147 | " background-color: rgba(0, 123, 255, 0.8);" 148 | " color: rgba(255, 255, 255, 0.9);" 149 | " border-radius: 15px;" 150 | "}" 151 | );} 152 | else{ 153 | ui->submit_but->setEnabled(false); 154 | ui->submit_but->setCursor(Qt::ArrowCursor); 155 | ui->submit_but->setStyleSheet( 156 | "QPushButton {" 157 | " font: 12pt 'Microsoft YaHei UI';" 158 | " background-color: rgb(167, 214, 255);" 159 | " color: white;" 160 | " border-radius: 15px;" 161 | "}" 162 | "QPushButton:hover {" 163 | " background-color: rgba(5, 186, 251, 0.7);" 164 | " color: white;" 165 | " border-radius: 15px;" 166 | "}" 167 | "QPushButton:pressed {" 168 | " background-color: rgba(0, 123, 255, 0.8);" 169 | " color: rgba(255, 255, 255, 0.9);" 170 | " border-radius: 15px;" 171 | "}" 172 | ); 173 | } 174 | } 175 | 176 | 177 | void RegisterWindow::on_cbbox_sex_currentIndexChanged(int index)//性别 178 | { 179 | on_line_answer_textChanged("arg"); 180 | } 181 | 182 | 183 | void RegisterWindow::on_line_password_textChanged(const QString &arg1)//密码 184 | { 185 | on_line_answer_textChanged(arg1); 186 | } 187 | 188 | 189 | void RegisterWindow::on_line_password2_textChanged(const QString &arg1)//确认密码 190 | { 191 | on_line_answer_textChanged(arg1); 192 | } 193 | 194 | 195 | void RegisterWindow::on_line_question_textChanged(const QString &arg1)//问题 196 | { 197 | on_line_answer_textChanged(arg1); 198 | } 199 | 200 | 201 | void RegisterWindow::on_line_nickname_textChanged(const QString &arg1)//昵称 202 | { 203 | on_line_answer_textChanged(arg1); 204 | } 205 | 206 | 207 | void RegisterWindow::on_submit_but_clicked(bool checked)//提交注册申请 两个密码不一致则弹窗 208 | { 209 | 210 | if(ui->line_password->text() != ui->line_password2->text()){ 211 | Dialog msgBox(this); 212 | QStyle *style = QApplication::style(); 213 | QIcon icon = style->standardIcon(QStyle::SP_MessageBoxWarning); 214 | msgBox.setWindowIcon(icon); 215 | msgBox.setWindowTitle("注册失败"); 216 | msgBox.transText("您的两次密码不一致!"); 217 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint|Qt::Dialog | Qt::FramelessWindowHint); 218 | msgBox.exec(); 219 | return; 220 | } 221 | if(socket == nullptr){//没连接到服务器 222 | Dialog msgBox(this); 223 | msgBox.transText("请检查您的网络连接!"); 224 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint|Qt::Dialog |Qt::FramelessWindowHint); 225 | msgBox.exec(); 226 | return;} 227 | qDebug() << "准备发送注册请求"; 228 | ui->submit_but->setEnabled(false); 229 | jsonObj = QJsonObject(); 230 | jsonObj["tag"] = "register"; 231 | jsonObj["nickname"] = ui->line_nickname->text(); 232 | jsonObj["gender"] = ui->cbbox_sex->currentText(); 233 | jsonObj["password"] = ui->line_password->text(); 234 | jsonObj["question"] = ui->line_question->text(); 235 | jsonObj["answer"] = ui->line_answer->text(); 236 | //发送消息 237 | jsonDoc = QJsonDocument(jsonObj); 238 | jsonData = jsonDoc.toJson(); 239 | //添加标识符 240 | QByteArray messageWithSeparator = jsonData + "END"; 241 | //发送JSON 数据 242 | socket->write(messageWithSeparator); 243 | socket->flush(); 244 | jsonData.clear(); 245 | qDebug() << "发送注册请求"; 246 | } 247 | 248 | 249 | void RegisterWindow:: receiveAvator(const QPixmap &pixmap)//收到用户选择的头像然后做相应处理 250 | { 251 | //处理圆角并更新图片 252 | ui->lab_avator->setPixmap(pixmap); 253 | ui->lab_avator->setScaledContents(true); 254 | } 255 | 256 | 257 | void RegisterWindow::sendAva()//发送头像给服务器 258 | { 259 | QPixmap pixmap = ui->lab_avator->pixmap(); 260 | if (pixmap.isNull()) { 261 | qDebug() << "头像不存在,无法发送"; 262 | return; 263 | } 264 | QByteArray byteArray; 265 | QBuffer buffer(&byteArray); 266 | if (!buffer.open(QIODevice::WriteOnly)) { 267 | qDebug() << "无法打开缓冲区,用于保存pixmap"; 268 | return; 269 | } 270 | if (!pixmap.save(&buffer, "PNG")) { 271 | qDebug() << "保存pixmap到缓冲区失败"; 272 | return; 273 | } 274 | QString avator = byteArray.toBase64(); 275 | jsonObj = QJsonObject(); 276 | jsonObj["tag"] = "myavator"; 277 | jsonObj["avator"] = avator; 278 | //发送消息 279 | jsonDoc = QJsonDocument(jsonObj); 280 | jsonData = jsonDoc.toJson(); 281 | //添加标识符 282 | QByteArray messageWithSeparator = jsonData + "END"; 283 | if (socket && socket->state() == QAbstractSocket::ConnectedState) { 284 | socket->write(messageWithSeparator); 285 | socket->flush(); 286 | } else { 287 | qDebug() << "Socket未连接,无法发送头像信息"; 288 | } 289 | qDebug() << "发送头像信息了"; 290 | jsonData.clear(); 291 | } 292 | 293 | 294 | void RegisterWindow::chengGong(QString qqnum)//注册成功 295 | { 296 | QString text = "

您的账号是:
" + qqnum + "," + "
请牢记!

"; 297 | Dialog* dialog = new Dialog(this); 298 | dialog->transText(text); 299 | dialog->exec(); 300 | this->disconnect(); 301 | this->close(); 302 | } 303 | 304 | 305 | void RegisterWindow::shiBai()//注册失败 306 | { 307 | Dialog msgBox(this); 308 | msgBox.transText("注册失败!"); 309 | msgBox.setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Dialog |Qt::FramelessWindowHint); 310 | msgBox.exec(); 311 | } 312 | 313 | 314 | void LineRegis::focusInEvent(QFocusEvent *event) 315 | { 316 | if(text() == "请输入昵称" || text() == "请输入问题" || text() == "请输入答案"){ 317 | setText(""); 318 | } 319 | setStyleSheet("font: 12pt 'Microsoft YaHei UI'; " 320 | "border: 1px solid rgba(0, 0, 0, 0.3); " 321 | "border-radius: 10px; " 322 | "color: black;"); 323 | if(this->text() == "请输入密码"||this->text() == "请确认密码"){ 324 | this->setEchoMode(QLineEdit::Password); 325 | setText(""); 326 | } 327 | QLineEdit::focusInEvent(event); 328 | } 329 | 330 | 331 | void LineRegis::focusOutEvent(QFocusEvent *event)//失去焦点处理事件 332 | { 333 | if(text() == ""){ 334 | if(objectName() == "line_nickname"){ 335 | setStyleSheet( 336 | "font: 12pt 'Microsoft YaHei UI'; " 337 | "border: 1px solid rgba(0, 0, 0, 0.3); " 338 | "border-radius: 8px; " 339 | "color: grey;" 340 | ); 341 | setText("请输入昵称"); 342 | } 343 | else if(objectName() == "line_password"){ 344 | setStyleSheet( 345 | "font: 12pt 'Microsoft YaHei UI'; " 346 | "border: 1px solid rgba(0, 0, 0, 0.3); " 347 | "border-radius: 8px; " 348 | "color: grey;" 349 | ); 350 | setText("请输入密码"); 351 | setEchoMode(QLineEdit::Normal); 352 | } 353 | else if(objectName() == "line_password2"){ 354 | setStyleSheet( 355 | "font: 12pt 'Microsoft YaHei UI'; " 356 | "border: 1px solid rgba(0, 0, 0, 0.3); " 357 | "border-radius: 8px; " 358 | "color: grey;" 359 | ); 360 | setText("请确认密码"); 361 | setEchoMode(QLineEdit::Normal); 362 | } 363 | else if(objectName() == "line_question"){ 364 | setStyleSheet( 365 | "font: 12pt 'Microsoft YaHei UI'; " 366 | "border: 1px solid rgba(0, 0, 0, 0.3); " 367 | "border-radius: 8px; " 368 | "color: grey;" 369 | ); 370 | setText("请输入问题"); 371 | } 372 | else if(objectName() == "line_answer"){ 373 | setStyleSheet( 374 | "font: 12pt 'Microsoft YaHei UI'; " 375 | "border: 1px solid rgba(0, 0, 0, 0.3); " 376 | "border-radius: 8px; " 377 | "color: grey;" 378 | ); 379 | setText("请输入答案"); 380 | } 381 | } 382 | QLineEdit::focusOutEvent(event); 383 | } 384 | 385 | 386 | void LabelRegis::mousePressEvent(QMouseEvent *event)//点击按钮更换头像 387 | { 388 | qDebug() << "点击头像了"; 389 | QString filename = QFileDialog::getOpenFileName(this, "选择图片", "", "Images (*.png *.jpg *.jpeg *.bmp *.gif)"); 390 | if (!filename.isEmpty()) { 391 | qDebug() << "头像路径有效"; 392 | QPixmap pixmap(filename); 393 | if (pixmap.isNull()) { 394 | qDebug() << "加载图片失败"; 395 | return; 396 | } 397 | //打开头像编辑器 398 | CutAvator *cutter = new CutAvator(filename); 399 | cutter->setWindowFlags(Qt::WindowStaysOnTopHint|Qt::Dialog); 400 | connect(cutter,&CutAvator::cutOk,qobject_cast(this->parentWidget()->parentWidget()),&RegisterWindow::receiveAvator); 401 | cutter->exec(); 402 | cutter->deleteLater(); 403 | } 404 | } 405 | 406 | -------------------------------------------------------------------------------- /user/user/registerwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef REGISTERWINDOW_H 2 | #define REGISTERWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace Ui { 26 | class RegisterWindow; 27 | } 28 | 29 | 30 | class RegisterWindow : public QMainWindow 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | explicit RegisterWindow(QTcpSocket *msocket,QWidget *parent = nullptr); 36 | ~RegisterWindow(); 37 | void setVal();//给输入框设置验证器 38 | void setAva();//设置默认头像 39 | QPixmap createCircularPixmap(const QString &imagePath);//设置图片的圆形掩码 40 | void paintEvent(QPaintEvent *event);//初始化背景 41 | QPixmap getRoundedPixmap(const QPixmap srcPixmap, const float radiusRatio);//切割圆角图片 42 | void closeEvent(QCloseEvent *event);//关闭事件 43 | void mousePressEvent(QMouseEvent *event);//点击窗口空白让所有输入框失去焦点 44 | 45 | private slots: 46 | void on_line_answer_textChanged(const QString &arg1);//文本改变 判断能不能提交 47 | //下面这几个槽函数都是判断能否点击提交按钮的 48 | void on_cbbox_sex_currentIndexChanged(int index);//性别 49 | void on_line_password_textChanged(const QString &arg1);//密码 50 | void on_line_password2_textChanged(const QString &arg1);//确认密码 51 | void on_line_question_textChanged(const QString &arg1);//问题 52 | void on_line_nickname_textChanged(const QString &arg1);//昵称 53 | void on_submit_but_clicked(bool checked);//提交注册申请 两个密码不一致则弹窗 54 | 55 | public slots: 56 | void receiveAvator(const QPixmap &pixmap);//收到用户选择的头像然后做相应处理 57 | void sendAva();//发送头像给服务器 58 | void chengGong(QString qqnum);//注册成功 59 | void shiBai();//注册失败 60 | 61 | private: 62 | Ui::RegisterWindow *ui; 63 | QTcpSocket *socket; 64 | QRegularExpressionValidator *validator; 65 | QJsonObject jsonObj; 66 | QJsonDocument jsonDoc; 67 | QByteArray jsonData; 68 | }; 69 | 70 | class LineRegis :public QLineEdit{ 71 | Q_OBJECT 72 | 73 | public: 74 | LineRegis(QWidget *parent = nullptr) : QLineEdit(parent) {} 75 | 76 | public slots: 77 | void focusInEvent(QFocusEvent *event);//获得焦点处理事件 78 | void focusOutEvent(QFocusEvent *event);//失去焦点处理事件 79 | }; 80 | 81 | class LabelRegis:public QLabel//点击头像更换头像 82 | { 83 | Q_OBJECT 84 | 85 | public: 86 | LabelRegis(QWidget *parent=nullptr):QLabel(parent){} 87 | void mousePressEvent(QMouseEvent *event);//点击头像更换头像 88 | }; 89 | 90 | #endif // REGISTERWINDOW_H 91 | -------------------------------------------------------------------------------- /user/user/user.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | QT += core network 3 | QT += widgets 4 | QT += sql 5 | RESOURCES += resource/tubiao.qrc 6 | 7 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 8 | 9 | CONFIG += c++17 10 | 11 | # You can make your code fail to compile if it uses deprecated APIs. 12 | # In order to do so, uncomment the following line. 13 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 14 | 15 | SOURCES += \ 16 | addfriends.cpp \ 17 | autocleartextedit.cpp \ 18 | changeinformation.cpp \ 19 | changepassword.cpp \ 20 | choicedialog.cpp \ 21 | cutavator.cpp \ 22 | dialog.cpp \ 23 | findpassword.cpp \ 24 | friendmessage.cpp \ 25 | logout.cpp \ 26 | main.cpp \ 27 | login.cpp \ 28 | mainwindow-else.cpp \ 29 | mainwindow.cpp \ 30 | registerwindow.cpp 31 | 32 | HEADERS += \ 33 | addfriends.h \ 34 | autocleartextedit.h \ 35 | changeinformation.h \ 36 | changepassword.h \ 37 | choicedialog.h \ 38 | cutavator.h \ 39 | dialog.h \ 40 | findpassword.h \ 41 | friendmessage.h \ 42 | login.h \ 43 | logout.h \ 44 | mainwindow-else.h \ 45 | mainwindow.h \ 46 | registerwindow.h 47 | 48 | FORMS += \ 49 | addfriends.ui \ 50 | changeinformation.ui \ 51 | changepassword.ui \ 52 | choicedialog.ui \ 53 | cutavator.ui \ 54 | dialog.ui \ 55 | findpassword.ui \ 56 | friendmessage.ui \ 57 | login.ui \ 58 | logout.ui \ 59 | mainwindow.ui \ 60 | registerwindow.ui 61 | 62 | TRANSLATIONS += \ 63 | user_zh_CN.ts 64 | CONFIG += lrelease 65 | CONFIG += embed_translations 66 | 67 | # Default rules for deployment. 68 | qnx: target.path = /tmp/$${TARGET}/bin 69 | else: unix:!android: target.path = /opt/$${TARGET}/bin 70 | !isEmpty(target.path): INSTALLS += target 71 | 72 | RESOURCES += \ 73 | ../../resource/tubiao.qrc 74 | -------------------------------------------------------------------------------- /user/user/user_zh_CN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------