由于组内人员调动原因,组长找了一个可以实现web、小程序、Android、ios的跨平台运行的框架uni-app,考虑到便利性,移动端的制作很重要,且该框架可以实现较多运行方式,考虑到时间因素和经验因素,故我和组长一起进行移动端的开发。PC端的制作内容会在本章内简单讲述,细节部分不再详谈,并暂停PC端开发,视后续情况再考虑是否继续。
目录
一、界面设计基础完善
1、聊天界面
布置了一个QTextEdit作为输入框,QListWidget作为输出框;
2、注册界面
新增了错误提示文字;(使用时,默认状态下全不可见,根据错误原因显示相应文字)
二、功能实现
1、登陆后拉取并展示所需数据
(1)拉取数据
登陆成功后,需要调用所给的可以拉取相应信息的接口,拉取最近会话列表、好友列表、群列表等并保存回调函数所传递的JSON文件,再将之展示出来;
//好友
void MainWindow::init_friendlist(){
int ret=TIMFriendshipGetFriendProfileList([](int32_t code, const char* desc, const char* json_params, const void* user_data){
if (ERR_SUCC != code){//失败
friendlist_success=false;
qDebug()<<"失败";
}
else{
QJsonParseError json_error;
QJsonDocument doucment = QJsonDocument::fromJson(json_params, &json_error);
if (json_error.error == QJsonParseError::NoError){
//qDebug()<<doucment;
if(doucment.isNull()){friendlist_success=false;}
else {friendlist_success=true;}
friendlist=doucment;
}
else{
qDebug()<<"error";
}
}
},nullptr);
QtConcurrent::run(this,&MainWindow::emit_getfrilist);
}
由于回调函数内无法直接调用函数,显示无法捕获this,而在[]中添加this则显示无对应函数可调用,找不到解决办法,最后发现可以使用全局变量保存数据,故后来使用全局变量保存,并再调用接口后另开线程(QtConcurrent)监听存储数据的全局变量是否非空(即传递过来的数据是否已保存),若非空则根据数据内容进行相应的后续处理。
此处由于多线程里只有主线程能对ui进行操作,故还需要其他线程发送信号让主线程接受并调用相应函数。
(其他回调函数带有数据的接口处理方法同上,后期不再提及)
//绑定相关信号与槽函数
connect(this,SIGNAL(getfrilist()),this,SLOT(set_friendlist()));
//发送已获取好友列表信号
void MainWindow::emit_getfrilist(){
while(friendlist.isNull()&&friendlist_success){if(!windowIsOpen) return;};
emit getfrilist();
}
//设置好友列表
void MainWindow::set_friendlist(){
QJsonDocument friend_list=friendlist;
//令重新为空
QJsonDocument theNUll;
friendlist=theNUll;
if(friend_list.isArray()){
const QJsonArray arr=friend_list.array();
//增加初始分组“我的好友”;
addNewFriGroup("我的好友");
for(int i=0;i<arr.size();i++){
QJsonObject oneOfFriend=arr[i].toObject();
addNewFriGroupBuddy(oneOfFriend);
}
}
}
(2)展示数据
各种列表使用QListWidget作为容器,在其中添加item后用自定义的不同的类(皆继承QWidget),将相应的内容放置于该类的变量中并调用setItemWidget替换;
ui->friend_list->setItemWidget(newItem,thefri);
聊天框消息内容从网上找了一个较为合适的聊天气泡与文字适配的相关代码,
void MessageFrame::adjustContent()
{
QTextDocument *document=qobject_cast<QTextDocument*>(sender());
document->adjustSize();
if(document)
{
document->setDocumentMargin(8);
QTextEdit *editor = qobject_cast<QTextEdit*>(document->parent()->parent());
if (editor) {
QString text = editor->toPlainText().trimmed();
if (text.isEmpty()) {
return;
}
QFontMetrics mert = editor->viewport()->fontMetrics();
int nCount = text.count("\n");
int width = mert.width(text);
int height = mert.height();
if (width > editor->maximumWidth() || (width < editor->maximumWidth() && nCount > 0)) {
float fheight = (width / (300*1.0)) + nCount;
int nheight = (width / (300*1.0)) + nCount;
float d = fheight - nheight;
if (fheight - nheight > 0 ) {
nheight ++;
}
if (d < 0.5) {
editor->setFixedSize(300, nheight * height + 28 );
} else {
editor->setFixedSize(300, nheight * height + 30 );
}
} else
{
editor->setFixedSize(width + 28, 36);
}
}
}
}
并且点击列表相应对象可以呈现其相关信息;
在聊天框处点击气泡旁边的头像也可以呈现相应用户信息。
(3)图片下载
从网上搜寻了有关使用QT通过url下载图片的方法并保存到指定文件夹(文件夹已在使用该程序时,即登陆界面初始化时便已判断是否存在并创建);
QString runPath = QCoreApplication::applicationDirPath();//获取当前运行程序所在目录
QString dirName=runPath+"/SdkFile";
QDir dir(dirName);
if(!dir.exists())
{
dir.mkdir(dirName);
qDebug()<<"文件夹创建成功";
}
dirName=runPath+"/PicSave";
QDir dirpic(dirName);//创建图片文件夹
if(!dir.exists())
{
dirpic.mkdir(dirName);
qDebug()<<"文件夹创建成功";
}
//判断图片是否存在
QString runPath= QCoreApplication::applicationDirPath();//获取当前运行程序所在目录
QString picid=m_pCurMessage.photo_large_id;
QString picpath=runPath+"/PicSave/"+picid;
QFileInfo fileinfo_tem(picpath);
if(fileinfo_tem.isFile()){
qDebug()<<"已存在";
}
else{
qDebug()<<"图片不存在";
downloadPicByUrl(m_pCurMessage.photo_large_url,picpath);
}
//图片下载 url
bool MessageFrame::downloadPicByUrl(const QString &url, const QString &fileName){
QNetworkAccessManager manager;
QNetworkRequest request;
request.setUrl(url);
// 发送请求
QNetworkReply *reply = manager.get(request);
//开启一个局部的事件循环,等待响应结束,退出
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
//判断是否出错,出错则结束
qDebug()<<reply->error();
if (reply->error() != QNetworkReply::NoError)
{
return false;
}
//保存文件
QFile file(fileName);
if(!file.open(QIODevice::ReadWrite)){
return false;
}
file.write(reply->readAll());
file.close();
delete reply;
return true;
}