Qt实现聊天机器人说话功能

如何在Qt项目中加入一个聊天机器人并采用tts技术使他”说话”?

api选择

选择国产图灵机器人,其接口:http://www.tuling123.com/api/product_exper/chat.jhtml,这是一个post请求接口,在后缀需加上?info=你要说的内容,返回的是一个xml格式的数据。需要相应格式解析,在.pro配置文件中加入QT += network xml。选择QTableView作为展示聊天记录的窗口,QStandardItemModel作为数据模型。
在头文件中引入网络模块

1
2
3
4
5
6
7
8
9
10
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QStandardItemModel>
class QTextToSpeech;
private:
QNetworkAccessManager *manage;
QStandardItemModel *session;
int rawCount;
QTextToSpeech *tts;

在cpp文件构造函数中初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <QUrlQuery>
#include <QMessageBox>
#include <QDomDocument>
#include <QTextToSpeech>

ui->btn_send->setEnabled(false); //发送按钮
connect(ui->textEdit_send,SIGNAL(textChanged()),this,SLOT(enableSendBtn()));
session = new QStandardItemModel(this);
// 自动延伸填满整个宽度
ui->tableView_session->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// 背景色交替
ui->tableView_session->setAlternatingRowColors(true);
ui->tableView_session->setStyleSheet("QTableView::item {alternate-background-color: #f3f4f5;}");
// 设置选中行背景色
ui->tableView_session->setStyleSheet("QTableView::item:selected {background-color: #F8F0DD;color: #3a3a3a;}");
//设置不显示格子线
ui->tableView_session->setShowGrid(false);
ui->tableView_session->setWordWrap(false);
ui->tableView_session->setModel(session);
rawCount =0; // 记录聊天量
tts = new QTextToSpeech(this);
tts->setLocale(QLocale::Chinese);

初始化进度管理

1
2
3
4
void chatRobot::Init(){
manage = new QNetworkAccessManager(this);
connect(manage, SIGNAL(finished(QNetworkReply*)), this, SLOT(readReply(QNetworkReply*)));
}

发送按钮只有在发送内容不为空才为真

1
2
3
4
5
6
7
void chatRobot::enableSendBtn(){
if(!ui->textEdit_send->toPlainText().isEmpty()){
ui->btn_send->setEnabled(true);
}else{
ui->btn_send->setEnabled(false);
}
}

发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void chatRobot::on_btn_send_clicked(){
// 接入图灵机器人聊天接口
QString RobotUrl = "http://www.tuling123.com/api/product_exper/chat.jhtml";
QNetworkRequest req;
QString word = ui->textEdit_send->toPlainText();
session->setItem(rawCount++, new QStandardItem(QIcon(":/images/me"), word));
// 根据内容自动调整行高
ui->tableView_session->resizeRowToContents(rawCount-1);
QUrl baseUrl(RobotUrl);
QUrlQuery query;
query.addQueryItem("info", word);
baseUrl.setQuery(query); //以后缀形式加在url后
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
req.setUrl(QUrl(baseUrl));
manage->post(req, "");
ui->btn_send->setEnabled(false); // 防止一条信息因错按发送按钮多次发送
}

接受服务器返回数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void chatRobot::readReply(QNetworkReply* reply){
QByteArray ans = reply->readAll();
QString strAns;
strAns.prepend(ans);// QByteArray转QString方法2
QString content;
QDomDocument doc;
int code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(code == 200){
doc.setContent(strAns);
QDomElement root = doc.documentElement(); //返回根节点
QDomNode node = root.firstChild(); //获得第一个子节点
while(!node.isNull()){ //如果节点不空
if(node.isElement()){ //如果节点是元素
QDomElement element=node.toElement(); //转换为元素
if(element.tagName() == "Content"){
content = element.text();
break;
}
}
node=node.nextSibling(); //下一个兄弟节点
}
session->setItem(rawCount++, new QStandardItem(QIcon(":/images/robot"), content));
ui->tableView_session->resizeRowToContents(rawCount-1);
// 文本转语音
tts->stop();
tts->say(content); // 播放
}else{
QMessageBox::warning(this,tr("warning"), tr("Network Error, HttpStatusCode: %1").arg(code),QMessageBox::Ok);
}
ui->btn_send->setEnabled(true);
}

大概运行效果如下
chat.png