效果如下:
源代码如下:
//common.h
#ifndef COMMON_H
#define COMMON_H
enum E_COLOR {
eWechatGreen,
eWhite
};
enum E_WHOSAY {
eMe,
eFriend
};
#define WECHATGREEN 152, 225, 101
#define WHITE 255,255,255
#endif // COMMON_H
//custommsgitem.h #ifndef CUSTOMMSGITEM_H #define CUSTOMMSGITEM_H #include#include "common.h" namespace Ui { class CustomMsgItem; } class QLabel; class CustomMsgItem : public QWidget { Q_OBJECT public: explicit CustomMsgItem(QWidget *parent = 0, E_WHOSAY = E_WHOSAY::eMe); ~CustomMsgItem(); void paintEvent(QPaintEvent *); void setMsg(QString strMsg); QString getMsg(); void setMsgBackgroudColor(E_COLOR); private: Ui::CustomMsgItem *ui; QString m_strMsg; QLabel *m_pLbMsg; QColor m_colorBackgroundMsg; E_WHOSAY m_eWhoSay; }; #endif // CUSTOMMSGITEM_H
//iknow.h #ifndef IKNOW_H #define IKNOW_H #include#include #include #include class QProcess; class IKnow : public QObject { Q_OBJECT public: IKnow(); ~IKnow(); QString answer(); void setQuestion(QString); bool findAnswer(); void exec(); signals: void signalFindAnswer(QString&); void sgnAnswreString(QString&); private slots: void recvStandOut(); protected slots: void OnGetReplyFromUrlRtn(QNetworkReply* pRply); private: QProcess *m_pProc; QString m_strAnswer; QString m_strQuestion; QNetworkAccessManager* m_pNetAcsMgr; }; #endif // IKNOW_H
```cpp //topaopao.h #ifndef TOPAOPAO_H #define TOPAOPAO_H #includenamespace Ui { class ToPaoPao; } class QVBoxLayout; class IKnow; class ToPaoPao : public QWidget { Q_OBJECT public: explicit ToPaoPao(QWidget *parent = 0); ~ToPaoPao(); void paintEvent(QPaintEvent *); bool eventFilter(QObject *, QEvent *); private slots: void on_btnSend_clicked(); void slotFindAnswer(QString&); void slider(); void OnGetRetString(QString&); private: Ui::ToPaoPao *ui; QVBoxLayout *m_pVboxLayout; IKnow *m_pIknow; QString m_strRet; }; #endif // TOPAOPAO_H
//custommsgitem.cpp #include "custommsgitem.h" #include "ui_custommsgitem.h" #include#include #include CustomMsgItem::CustomMsgItem(QWidget *parent, E_WHOSAY eWhoSay) : QWidget(parent), ui(new Ui::CustomMsgItem), m_strMsg(""), m_colorBackgroundMsg(WECHATGREEN), m_eWhoSay(eWhoSay) { ui->setupUi(this); m_pLbMsg = new QLabel(this); m_pLbMsg->setTextInteractionFlags(Qt::TextSelectableByMouse); ui->horizontalLayout->addWidget(m_pLbMsg); m_pLbMsg->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); QFont font; font.setPixelSize(20); m_pLbMsg->setFont(font); m_pLbMsg->setWordWrap(true); } CustomMsgItem::~CustomMsgItem() { delete ui; } void CustomMsgItem::paintEvent(QPaintEvent *) { m_pLbMsg->setText(m_strMsg); //根据当前文字长度设置气泡长度 QFontMetrics fontMetrics(m_pLbMsg->font()); //如果当前字体长度大于窗体宽度的二分之一 //就不断分割 if (fontMetrics.width(m_pLbMsg->text()) > this->parentWidget()->width() / 2) { setFixedWidth(30 + this->parentWidget()->width() / 2); int iLine = (fontMetrics.width(m_pLbMsg->text()) % (this->parentWidget()->width() / 2)) == 0 ? 0 : fontMetrics.height(); setFixedHeight(30 + fontMetrics.height() * ((fontMetrics.width(m_pLbMsg->text()) / (this->parentWidget()->width() / 2))) + iLine); } else { setFixedWidth(fontMetrics.width(m_pLbMsg->text()) + 30); setFixedHeight(fontMetrics.height() + 25); } QPainter painter(this); QRectF rectangle; QPainterPath trianglePath; if (m_eWhoSay == E_WHOSAY::eMe) { rectangle = QRectF(0, 0, width() - 5, height()); trianglePath = QPainterPath(QPointF(width() - 5, height() / 2 - 7)); trianglePath.lineTo(width(), height() / 2); trianglePath.lineTo(width() - 5, height() / 2 + 7); trianglePath.lineTo(width() - 5, height() / 2 - 7); } else if (m_eWhoSay == E_WHOSAY::eFriend) { m_colorBackgroundMsg.setRgb(WHITE); rectangle = QRectF(5, 0, width() - 5, height()); trianglePath = QPainterPath(QPointF(5, height() / 2 - 7)); trianglePath.lineTo(0, height() / 2); trianglePath.lineTo(5, height() / 2 + 7); trianglePath.lineTo(5, height() / 2 - 7); } painter.setPen(Qt::NoPen); painter.setBrush(m_colorBackgroundMsg); //画矩形 painter.drawRoundedRect(rectangle, 5.0, 5.0); //画三角形 painter.drawPath(trianglePath); } void CustomMsgItem::setMsg(QString strMsg) { this->m_strMsg = strMsg; } QString CustomMsgItem::getMsg() { return m_strMsg; } void CustomMsgItem::setMsgBackgroudColor(E_COLOR eColor) { if (eColor == E_COLOR::eWechatGreen) { m_colorBackgroundMsg.setRgb(WECHATGREEN); } else if (eColor == E_COLOR::eWhite) { m_colorBackgroundMsg.setRgb(WHITE); } }
//iknow.cpp #include "iknow.h" #include#include #include #include #include #include #include #include IKnow::IKnow() { m_pNetAcsMgr = new QNetworkAccessManager(this); QString strPorc = QCoreApplication::applicationDirPath() + "/IKNOW.exe"; m_pProc = new QProcess(); m_pProc->setReadChannel(QProcess::StandardOutput); m_pProc->start(strPorc); connect(m_pProc, SIGNAL(readyReadStandardOutput()), this, SLOT(recvStandOut())); } IKnow::~IKnow() { m_pProc->kill(); delete m_pProc; m_pProc = nullptr; } void IKnow::recvStandOut() { exec(); } QString IKnow::answer() { return m_strQuestion; } void IKnow::setQuestion(QString strQuestion) { //向IKNOW.exe发送消息 m_strQuestion = strQuestion; } void IKnow::OnGetReplyFromUrlRtn(QNetworkReply* pRply) { int iError = pRply->error(); if (iError == QNetworkReply::NoError) { QByteArray bytes = pRply->readAll(); QString jsonString = QString::fromUtf8(bytes); QJsonParseError jsonParseError; QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes, &jsonParseError); if (!jsonDoc.isNull() && jsonParseError.error == QJsonParseError::NoError) { if (jsonDoc.isArray()) { } else { QJsonObject jsonObject = jsonDoc.object(); QString strRet = jsonObject["content"].toString(); //用换车替换{br} strRet.replace("{br}", QChar('n')); emit signalFindAnswer(strRet); } } else { } } } bool IKnow::findAnswer() { //收到IKNOW.exe的消息 // 方案1.根据C++调用python进程来获取答案 //方案2.C++独立请求后台接口来得到答案 QObject::connect(m_pNetAcsMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(OnGetReplyFromUrlRtn(QNetworkReply*))); QString strUrl = QString("http://api.qingyunke.com/api.php?key=free&appid=0&msg=%1").arg(m_strQuestion); QUrl url(strUrl); QNetworkRequest req(url); req.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=utf-8")); m_pNetAcsMgr->get(req); return true; } void IKnow::exec() { if (findAnswer()) { //emit signalFindAnswer(); } }
//topaopao.cpp #include "topaopao.h" #include "ui_topaopao.h" #include "custommsgitem.h" #include "common.h" #include "iknow.h" #include#include #include #include #include ToPaoPao::ToPaoPao(QWidget *parent) : QWidget(parent), ui(new Ui::ToPaoPao) { ui->setupUi(this); setFocus(); m_pVboxLayout = new QVBoxLayout(); ui->scrollAreaWidgetContents_2->setLayout(m_pVboxLayout); m_pIknow = new IKnow(); connect(m_pIknow, SIGNAL(signalFindAnswer(QString&)), this, SLOT(slotFindAnswer(QString&))); connect(m_pIknow, SIGNAL(sgnAnswreString(QString&)), this, SLOT(OnGetRetString(QString&))); ui->texteditInput->installEventFilter(this); QString strQuestion = ui->texteditInput->toPlainText(); m_pIknow->setQuestion(strQuestion); connect(ui->scrollArea->verticalScrollBar(), &QAbstractSlider::rangeChanged, this, &ToPaoPao::slider); } ToPaoPao::~ToPaoPao() { delete m_pIknow; delete m_pVboxLayout; delete ui; } void ToPaoPao::slider() { ui->scrollArea->verticalScrollBar()->setValue(ui->scrollArea->verticalScrollBar()->maximum()); } void ToPaoPao::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); } bool ToPaoPao::eventFilter(QObject *pObj, QEvent *pEvent) { if (pObj == ui->texteditInput) { QKeyEvent *pKeyEvent = dynamic_cast (pEvent); if (pKeyEvent) { if (pKeyEvent->key() == Qt::Key_Return || pKeyEvent->key() == Qt::Key_Return) { on_btnSend_clicked(); } } } return QWidget::eventFilter(pObj, pEvent); } void ToPaoPao::slotFindAnswer(QString& strAnswer) { QHBoxLayout *pHboxLayout = new QHBoxLayout(); CustomMsgItem *pItem = new CustomMsgItem(ui->scrollAreaWidgetContents_2, E_WHOSAY::eFriend); pHboxLayout->addWidget(pItem); pHboxLayout->insertStretch(1); pItem->setMsg(strAnswer); //pItem->setMsg(m_pIknow->answer()); m_pVboxLayout->addLayout(pHboxLayout); } void ToPaoPao::OnGetRetString(QString& strRet) { m_strRet = strRet; } void ToPaoPao::on_btnSend_clicked() { QString strInput = ui->texteditInput->toPlainText(); //去除回车 strInput.remove(QChar('n')); ui->texteditInput->clear(); //判断输入框是否为空 if (strInput.isEmpty()) { return ; } QHBoxLayout *pHboxLayout = new QHBoxLayout(); CustomMsgItem *pItem = new CustomMsgItem(ui->scrollAreaWidgetContents_2, E_WHOSAY::eMe); pHboxLayout->insertStretch(0); pHboxLayout->addWidget(pItem); pItem->setMsg(strInput); m_pVboxLayout->addLayout(pHboxLayout); m_pIknow->setQuestion(strInput); m_pIknow->findAnswer(); }



