QT--聊天室
一、设计要求
用QT做一个聊天室,
制作一个服务器和客户端。可以进行注册、登录,
登陆成功后可以使用昵称进行发送、接收消息。
能根据昵称、聊天内容查询历史记录,也可以查询全部聊天记录。
。
二、客户端三级ui界面
三、项目代码
//在pro文件里加入
QT += core gui network
RC_FILE += icon_config.rc
//客户端dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QtWidgets>
#include <QDebug>
// 网络连接类
#include <QTcpSocket>
// 文本流
#include <QTextStream>
#include <QDateTime>
#include <QByteArray>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;QTcpSocket *client;void printMsg(QString); // 输出内容到公屏void succRight();private slots:void btnConnClickedSlot(); // 连接按钮void btnSendClickedSlot(); // 发送按钮void connectedSlot(); // 连接成功的槽函数void disconnectedSlot(); // 断开连接的槽函数void readReadSlot(); // 接收数据的槽函数void btnHisClickedSlot();//历史记录void btnHisNameClickedSlot();//按照昵称void btnHisNeiClickedSlot();//按照内容void btnLoginClickedSlot();//登录/切换窗口void btnRegClickedSlot();//注册};#endif // DIALOG_H
//客户端dialog.c
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{ui->setupUi(this);// 抢前台setWindowFlags(Qt::WindowStaysOnTopHint);connect(ui->pushButtonConn,SIGNAL(clicked()),this,SLOT(btnConnClickedSlot()));connect(ui->pushButtonSend,SIGNAL(clicked()),this,SLOT(btnSendClickedSlot()));client = new QTcpSocket(this);// 建立网络连接检测的信号槽connect(client,SIGNAL(connected()),this,SLOT(connectedSlot()));connect(client,SIGNAL(disconnected()),this,SLOT(disconnectedSlot()));// 接收消息的信号槽connect(client,SIGNAL(readyRead()),this,SLOT(readReadSlot()));
//历史connect(ui->pushButtonHis,SIGNAL(clicked()),this,SLOT(btnHisClickedSlot()));connect(ui->pushButtonName,SIGNAL(clicked()),this,SLOT(btnHisNameClickedSlot()));connect(ui->pushButtonNei,SIGNAL(clicked()),this,SLOT(btnHisNeiClickedSlot()));//切换窗口:登录connect(ui->pushButtonLo,SIGNAL(clicked()),this,SLOT(btnLoginClickedSlot()));//注册connect(ui->pushButtonReg,SIGNAL(clicked()),this,SLOT(btnRegClickedSlot()));}Dialog::~Dialog()
{disconnect(client,SIGNAL(disconnected()),this,SLOT(disconnectedSlot()));// 如果还在连接if(client->isOpen())client->close();delete ui;
}void Dialog::btnConnClickedSlot()
{// 发起连接请求// 默认用户输入的参数都对client->connectToHost(ui->lineEditIp->text(),ui->spinBox->value());
}void Dialog::printMsg(QString msg)
{// 获得当前时间QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh:mm:ss");ui->textBrowser->append(time);ui->textBrowser->append(msg);ui->textBrowser->append("");
}void Dialog::succRight()
{ui->stackedWidget->setCurrentIndex(1);
}void Dialog::btnSendClickedSlot()
{// 获得昵称和消息内容QString user = ui->lineEditUser->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString msg = ui->lineEditMsg->text();if(msg == ""){QMessageBox::warning(this,"提示","请输入要发送的消息!");return;}QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");// 创建文本流对象QTextStream output(client);// 连续输出发送output << time<<":"<<user << ":" << msg;// 清空消息输入框ui->lineEditMsg->clear();// 公屏显示msg = user+QString("(本机):")+msg;printMsg(msg);
}void Dialog::connectedSlot()
{// 屏蔽连接按钮,开启发送按钮ui->pushButtonConn->setEnabled(false);ui->pushButtonConn->setText("已连接");ui->pushButtonSend->setEnabled(true);ui->stackedWidget->setCurrentIndex(1);
}void Dialog::readReadSlot()
{QTextStream input(client);QString text = input.readAll();QString text1=input.readLine(100);qDebug() <<text1;QStringList list = text.split(":");QStringList list2 = text1.split(":");qDebug()<<"分割后数量"<<list.size();qDebug() <<list2.size();if(list.size()<4){if(text=="dlchengg"){qDebug() <<text;ui->stackedWidget->setCurrentIndex(2);ui->textBrowser->clear();}
// else if(list.size()==3)
// {// ui->textBrowser_2->append(text);
// return;
// }else{printMsg(text);}}else if(list.size()>=4){ui->textBrowser_2->append(text);return;}
}void Dialog::btnHisClickedSlot()
{ui->textBrowser_2->clear();QString user = ui->lineEditUser->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");// 创建文本流对象QTextStream output(client);QString mm="历史记录";output<< time<<":"<<user << ":" <<mm ;
}void Dialog::btnHisNameClickedSlot()
{ui->textBrowser_2->clear();QString user = ui->lineEditUser->text();QString time = "hh";// 创建文本流对象QTextStream output(client);QString mm="按照昵称";output<< time<<":"<<user << ":" <<mm ;
}void Dialog::btnHisNeiClickedSlot()
{ui->textBrowser_2->clear();QString user = "sjdhs";QString time = "按照内容";// 创建文本流对象QString msg = ui->lineEditMsg->text();if(msg == ""){QMessageBox::warning(this,"提示","请输入要发送的消息!");return;}QTextStream output(client);output<< time<<":"<<user << ":" <<msg ;
}void Dialog::btnLoginClickedSlot()
{QString user = ui->lineEditUs->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString pwd = ui->lineEdit_2Pwd->text();if(pwd == ""){QMessageBox::warning(this,"提示","请输入密码!");return;}// 创建文本流对象QTextStream output(client);// 连续输出发送QString mag="hha";QString haf="lele";output <<user << ":" << pwd<<":"<<mag<<":"<<haf;}void Dialog::btnRegClickedSlot()
{QString user = ui->lineEditUs->text();if(user==""){QMessageBox::warning(this,"提示","请输入昵称!");return;}QString pwd = ui->lineEdit_2Pwd->text();if(pwd == ""){QMessageBox::warning(this,"提示","请输入密码!");return;}// 创建文本流对象QTextStream output(client);// 连续输出发送output <<user << ":" << pwd;
}void Dialog::disconnectedSlot()
{// 开启连接按钮,屏蔽发送按钮ui->pushButtonConn->setEnabled(true);ui->pushButtonConn->setText("连接");ui->pushButtonSend->setEnabled(false);// 弹窗printMsg("连接已断开!");QMessageBox::warning(this,"提示","连接已断开!");ui->stackedWidget->setCurrentIndex(0);
}
//服务器dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QtWidgets>
#include <QDebug>
// 连接管理类
#include <QTcpServer>
#include <QDateTime>
// 连接类
#include <QTcpSocket>
// 文本流
#include <QTextStream>#include <QButtonGroup>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlQuery>
#include <QByteArray>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;QTcpServer* server; // 管理对象(母鸡)void printMsg(QString); // 输出内容到公屏QTcpSocket* socket = NULL; // 连接对象(绿蛋)QList<QTcpSocket*> sockets;QList<QString> ips;QSqlDatabase db;void connect2DB(); // 连接到数据库1void createTable();// 建表void createTable2();void insertData(); // 插入数据void selectAll(int); // 数据全查void selectLOgin(QString,QString,int);void selectName(QString,int);void selectNei(QString,int);private slots:// 新连接来了的槽函数void newConnSlot();// 连接掉线的信号槽void disconnetedSlot();// 有数据可读时的槽函数void readyReadSlot();};#endif // DIALOG_H
//服务器dialog.c
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{ui->setupUi(this);// 抢前台setWindowFlags(Qt::WindowStaysOnTopHint);server = new QTcpServer(this);// 连接新连接来了的信号槽connect(server,SIGNAL(newConnection()),this,SLOT(newConnSlot()));// 开启监听服务server->listen(QHostAddress::Any,8887);connect2DB();
}Dialog::~Dialog()
{if(server->isListening()) // 如果还在监听server->close();delete ui;
}void Dialog::printMsg(QString msg)
{// 获得当前时间QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");ui->textBrowser->append(time);ui->textBrowser->append(msg);ui->textBrowser->append("");
}void Dialog::connect2DB()
{// 创建连接对象db = QSqlDatabase::addDatabase("QSQLITE");// 设置数据库的文件名称db.setDatabaseName("book_management.db");// 打开数据库if(db.open()){qDebug() << "连接成功";// createTable();// createTable2();}else{// 获得错误信息封装类QSqlError info = db.lastError();// 提取错误文本QString text = info.text();// 展示错误QMessageBox::critical(this,"错误",text);}}void Dialog::createTable()
{QString sql = "CREATE TABLE book(time TEXT PRIMARY KEY,name TEXT,msg TEXT);";// 创建数据库操作类对象QSqlQuery sq;if(sq.exec(sql)){qDebug() << "建表成功";}else// 失败{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误qDebug() << text;}}void Dialog::createTable2()
{QString sql2 = "CREATE TABLE class(name TEXT PRIMARY KEY,pwd TEXT);";// 创建数据库操作类对象QSqlQuery sq;if(sq.exec(sql2)){qDebug() << "建表2成功";}else// 失败{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误qDebug() << text;}
}void Dialog::selectAll(int i)
{QString sql = "SELECT * FROM book";QSqlQuery sq;sq.prepare(sql);if(sq.exec(sql)){// 清空上次显示// ui->textBrowser->clear();while(sq.next())// 循环取出{// 取出一条数据库中的字段QString time = sq.value(0).toString();QString name = sq.value(1).toString();QString msg = sq.value(2).toString();QString msa="历史";// 拼接并显示QString text = msa.append(":")+ time.append(":")+ name.append(":") + msg;QTextStream output(sockets.at(i));output<< text<<endl;}}}void Dialog::selectLOgin(QString user, QString pwd2,int i)
{QString name=user;QString pwd=pwd2;QString sql = "SELECT * FROM class WHERE name LIKE ? AND pwd LIKE ?;";QSqlQuery sq;sq.prepare(sql);if(sq.exec(sql)){while(sq.next()){qDebug() << "yes";QString user = sq.value(0).toString();QString pwd = sq.value(1).toString();QString text ="dlchengg";QTextStream output(sockets.at(i));output<<text;}}else{QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();text.prepend("登录失败:");QMessageBox::warning(this,"警告",text);}
}void Dialog::selectName(QString name1,int i)
{QString name=name1;QString sql = "SELECT * FROM book WHERE name LIKE ?";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(name);if(sq.exec()){while(sq.next())// 循环取出{// 取出一条数据库中的字段QString time = sq.value(0).toString();QString name = sq.value(1).toString();QString msg = sq.value(2).toString();QString msa="历史";// 拼接并显示QString text = msa.append(":")+time.append(":")+ name.append(":") + msg;QTextStream output(sockets.at(i));output<< text<<endl;}}
}void Dialog::selectNei(QString msg, int i)
{QString sql = "SELECT * FROM book WHERE msg LIKE ?";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(msg.prepend("%").append("%"));if(sq.exec()){while(sq.next())// 循环取出{// 取出一条数据库中的字段QString time = sq.value(0).toString();QString name = sq.value(1).toString();QString msg = sq.value(2).toString();QString msa="历史";// 拼接并显示QString text = msa.append(":")+time.append(":")+ name.append(":") + msg;QTextStream output(sockets.at(i));output<< text<<endl;}}
}void Dialog::newConnSlot()
{// 获得服务器端的连接类对象socket = server->nextPendingConnection();QTextStream output(socket);// 如果满员则踢出if(sockets.size() == 20){qDebug() << "聊天室满员";output << QString("聊天室已达人数上限,连接失败!");socket->close();return;}sockets.append(socket);// 绿蛋收到消息的信号槽connect(socket,SIGNAL(readyRead()),this,SLOT(readyReadSlot()));// 绿蛋掉线的信号槽connect(socket,SIGNAL(disconnected()),this,SLOT(disconnetedSlot()));// 给客户端打个招呼output << QString("服务器:你好啊!");// 获得对面的IP地址和端口号QString ip = socket->peerAddress().toString();quint16 port = socket->peerPort();QString portText = QString::number(port);QString text = "新连接来了!";text.append(ip).append(":").append(portText);printMsg(text);
}void Dialog::disconnetedSlot()
{// 拿到发射者socket = (QTcpSocket*)sender();for(int i = 0;i<sockets.size();i++){if(socket == sockets.at(i)){qDebug() << "第" << i << "个客户端掉线了";// 获得对面的IP地址和端口号QString ip = sockets.at(i)->peerAddress().toString();quint16 port = sockets.at(i)->peerPort();QString portText = QString::number(port);QString text = "连接已断开!";text.append(ip).append(":").append(portText);printMsg(text);sockets.removeAt(i);}}
}//接收数据
void Dialog::readyReadSlot()
{for(int i=0;i<sockets.size();i++){if(sockets.at(i)->isReadable() && sockets.at(i)->bytesAvailable()>0){qDebug() << "第" << i << "个客户端发的消息";QTextStream input(sockets.at(i));// 一口气都读了QString text = input.readAll();//写入数据库QStringList list = text.split(":");qDebug()<<"分割后数量"<<list.size();if(list.size()==3){QString time = list[0];QString name = list[1];QString msg = list[2];if(list[2]=="历史记录"){selectAll( i);}else if(list[2]=="按照昵称"){selectName(name,i);}else if(list[0]=="按照内容"){selectNei(msg,i);}else{createTable();QString sql = "INSERT INTO book VALUES(?,?,?);";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(time);sq.addBindValue(name);sq.addBindValue(msg);if(sq.exec()){qDebug()<<"数据插入成功";// QMessageBox::information(this,"通知","数据插入成功");}else{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误text.prepend("数据插入失败:");QMessageBox::warning(this,"警告",text);}printMsg(text);for(int m=0;m<sockets.size();m++){if(m==i)continue;QTextStream output(sockets.at(m));output << text;}}}else if(list.size()==2){createTable2();QString name = list[0];QString pwd = list[1];QString sql = "INSERT INTO class VALUES(?,?);";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(name);sq.addBindValue(pwd);if(sq.exec()){qDebug()<<"注册成功";// QMessageBox::information(this,"通知","数据插入成功");}else{// 获得错误信息封装类QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();// 展示错误text.prepend("注册失败:");QMessageBox::warning(this,"警告",text);}printMsg(text);for(int m=0;m<sockets.size();m++){if(m==i)continue;QTextStream output(sockets.at(m));output << text;}}else if(list.size()==4){QString name = list[0];QString pwd = list[1];qDebug() << name<<pwd;QString sql = "SELECT * FROM class WHERE name=? AND pwd=?";QSqlQuery sq;sq.prepare(sql);sq.addBindValue(name);sq.addBindValue(pwd);qDebug() << "yes";if(sq.exec()){// 取出一条数据库中的字段while(sq.next()){QString name = sq.value(0).toString();QString pwd = sq.value(1).toString();qDebug() <<name<<pwd;qDebug() << "yes";QString text ="dlchengg";QTextStream output(sockets.at(i));output<<text;}}else{QSqlError info = sq.lastError();// 提取错误文本QString text = info.text();text.prepend("登录失败:");QMessageBox::warning(this,"警告",text);}}}}}
四、项目结果
相关文章:

QT--聊天室
一、设计要求 用QT做一个聊天室, 制作一个服务器和客户端。可以进行注册、登录, 登陆成功后可以使用昵称进行发送、接收消息。 能根据昵称、聊天内容查询历史记录,也可以查询全部聊天记录。 。 二、客户端三级ui界面 三、项目代码 //在…...
Javascript前端面试基础4【每日学习并更新10】
同步和异步的区别 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等…...

社区团购系统搭建开发,前端uniapp。社区团购搭建开发定制
目录 前言: 一、社区团购系统有哪些功能? 二、社区团购管理端 三、社区团购的基本流程如下: 总结 : 前言: 社区团购是一种以社区为单位进行的集体购物模式。这种模式利用了互联网平台来组织同一社区内的居民一起购…...

node+mysql+layui+ejs实现左侧导航栏菜单动态显示
nodemysqllayuiejs实现左侧导航菜单动态显示 实现思路效果图数据库技术栈代码实现main.html(前端首页页面)查询资源菜单方法 jsapp.js配置ejs模板 node入门到入土项目实战开始,前端篇项目适合node小白入门,因为我也是小白来学习no…...

FRP配置内网穿透52版本以上适用
简述 适用frp配置内网穿透来说我们需要进行简单的区分,具有公网IP的服务器我们简称为服务端,内网的服务器我们可以简称为客户端,frp需要针对不同的服务器配置不同的文件 下载安装包 Linux下载地址 https://github.com/fatedier/frp/relea…...

IFM易福门LR3000LR3300液位传感器操作说明
IFM易福门LR3000LR3300液位传感器操作说明...

【Python大语言模型系列】基于阿里云人工智能平台采用P-Tuning v2微调ChatGLM2-6B大模型(完整教程)
这是我的第331篇原创文章。 一、引言 P-Tuning 是一种对预训练语言模型进行少量参数微调的技术。所谓预训练语言模型,就是指在大规模的语言数据集上训练好的、能够理解自然语言表达并从中学习语言知识的模型。P-Tuning 所做的就是根据具体的任务,对预训练…...

基于Spring boot + Vue的加油站系统
项目名称:加油站系统 作者的B站地址:程序员云翼的个人空间-程序员云翼个人主页-哔哩哔哩视频 csdn地址:程序员云翼-CSDN博客 1.项目技术栈: 前后端分离的项目 后端:Springboot MybatisPlus 前端:Vue…...
️RPC协议 --基于TCP实现RPC通信
RPC 协议介绍 RPC(Remote Procedure Call,远程过程调用)协议是一种通信协议,允许一个程序调用另一个地址空间(通常是在网络上)的过程或函数,而不需要显式地处理细节如数据序列化和网络通信。它允许开发人员编写分布式应用程序,就像编写本地应用程序一样。 关键特点和组…...

android(安卓)最简单明了解释版本控制之MinSdkVersion、CompileSdkVersion、TargetSdkVersion
1、先明白几个概念 (1)平台版本(Android SDK版本号) 平台版本也就是我们平时说的安卓8、安卓9、安卓10 (2)API级别(API Level) Android 平台提供的框架 API 被称作“API 级别” …...

Redis缓存穿透、击穿和雪崩的理解和解决思路
Redis的缓存穿透 缓存穿透是指那些查询请求所要获取的数据既不在缓存(Redis)中,也不在数据库(例如:MySQL)中,因此每次请求都会直接访问数据库。这种情况通常由以下几种情形引起: 恶…...

ReactHooks(完结)
上期戳here ReactHooks[三] 一.memo 函数1.1 语法格式 二. useMemo2.1 问题引入2.2 语法格式2.3 使用 useMemo 解决刚才的问题 三.useCallback3.1 useMemo和useCallback区别3.2 语法格式 四.useTransition4.1 问题引入4.2 语法格式4.3 使用 isPending 展示加载状态4.4 注意事项…...

【数据中台】大数据管理平台建设方案(原件资料)
建设大数据管理中台,按照统一的数据规范和标准体系,构建统一数据采集﹣治理﹣共享标准、统一技术开发体系、统一接口 API ,实现数据采集、平台治理,业务应用三层解耦,并按照统一标准格式提供高效的…...

UE5+OpenCV配置(Windows11系统)
一、概述 因为需要在UE5中使用OpenCV这些工具进行配置,所以在网络上参考借鉴一些资料进行配置。查询到不少的资料,最后将其配置成功。在这里顺便记录一下自己的配置成功的过程。 二、具体过程 (一)版本 使用Windows11系统、UE5.…...

自研Vue3开源Tree组件:节点拖拽bug修复
当dropType为after,且dropNode为父节点时,bug出现了: bug原因:插入扁平化列表的位置insertIndex计算的不对: 正确的逻辑,同inner要算上子孙节点所占的位置: bug修复!...

SSM学习9:SpringBoot简介、创建项目、配置文件、多环节配置
简介 SpringBoot式用来简化Spring应用的初始搭建以及开发过程的一个框架 项目搭建 File -> New -> Project 选中pom.xml文件,设置为maven项目 项目启动成功 可以访问BasicController中的路径 配置文件 在resources目录下 application.properties 默…...
Java面试题---索引
什么是索引 索引是用来高效获取数据的存储结构如同字典的目录一样,数据库的索引通常使用btree来实现,索引树的节点和数据地址相关联,查询的时候在索引树种进行高效搜索,然后根据数据地址获取数据。索引提高了搜索的效率同时增加了…...

ollama本地部署大语言模型记录
目录 安装Ollama更改模型存放位置 拉取模型GemmaMistralQwen1.5(通义千问)codellama 部署Open webui测试性能知识广度问题1问题2 代码能力总结 最近突然对大语言模型感兴趣 同时在平时的一些线下断网的CTF比赛中,大语言模型也可以作为一个能对话交互的高级知识检索…...

【C++红黑树应用】模拟实现STL中的map与set
目录 🚀 前言一: 🔥 红黑树的修改二: 🔥 红黑树的迭代器 三: 🔥 perator() 与 operator--() 四: 🔥 红黑树相关接口的改造✨ 4.1 Find 函数的改造✨ 4.2 Insert 函数的改…...
前端实习手计(5):班味十足?!
自我感觉没有班味!!!每天还是快快乐乐上班哇,是愉快的一周~这周没有太多活咯,基本就是修修改改改代码学习。真的感觉自己写的代码就是乱七八糟,只要能跑起来有效果就行(我不是合格的处女座哈哈哈…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...