最开始没有接触过qt,至今也不是特表清晰,凭自己的理解记录一下前端与qt的套壳开发。
一、qwebkit嵌套html页面。
首先在资源文件放置html文件,我的文件名称:style-new.html
<html>
<head>
<style>
html,body,head,table{margin:0px; padding: 0px; border: 0px;}
img,div{border: 0px;}
/*谷歌、safari、qq浏览器、360浏览器滚动条样式*/
/*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar
{
width: 8px;
height: 8px;
background-color: #F8F9FB;
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 0px rgba(170,170,170,0.2);
border-radius: 8px;
background-color: #F8F9FB;
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb
{
border-radius: 8px;
-webkit-box-shadow: inset 0 0 0px rgba(170,170,170,.2);
background-color: #EEEEEE;
}
/*滑块效果*/
::-webkit-scrollbar-thumb:hover
{
border-radius: 5px;
-webkit-box-shadow: inset 0 0 0px rgba(226,226,226,0.2);
background: #E2E2E2;
}
</style>
</head>
<body id="content" style="background: #f8f9fb;">
<script>
//此函数为:向qt发送信号参数:a为当前文件id唯一标识;aa为状态:0-发送离线文件;1-取消;2-打开文件夹;3-打开文件;4-接收;5-下载
//测试函数
function sendToRcv(a,aa){
window.mywebkit.onHtmlCall(a,aa);
}
//图片传输
function sendToImg(i){
window.mywebkit.onHtmlCallPic(i);
}
//绝密会话 e=id 0-拒绝;1-接受;
function sendSecret(e,ee){
window.mywebkit.onHtmlCallAcceptSecretChat(e,ee);
document.getElementById(e).style.display="none";
}
//文件传输
function sendFile(c,cc){
window.mywebkit.onHtmlCallFile(c,cc);
}
//阅后即焚
var mySecret = new Array();
function readAfter(sa,sb,sc){
var mySecretLenght=mySecret.length;
for(var i=0;i<mySecretLenght;i++)
{
if(mySecret[i]==sa){
return;
}
}
mySecret.push(sa);
document.getElementById(sc).style.display="block";
var t9=setTimeout(function(){document.getElementById(sb).innerHTML='9'},2000);
var t8=setTimeout(function(){document.getElementById(sb).innerHTML='8'},3000);
var t7=setTimeout(function(){document.getElementById(sb).innerHTML='7'},4000);
var t6=setTimeout(function(){document.getElementById(sb).innerHTML='6'},5000);
var t5=setTimeout(function(){document.getElementById(sb).innerHTML='5'},6000);
var t4=setTimeout(function(){document.getElementById(sb).innerHTML='4'},7000);
var t3=setTimeout(function(){document.getElementById(sb).innerHTML='3'},8000);
var t2=setTimeout(function(){document.getElementById(sb).innerHTML='2'},9000);
var t1=setTimeout(function(){document.getElementById(sb).innerHTML='1'},10000);
var t0=setTimeout(function(){document.getElementById(sb).innerHTML='0'},11000);
var t11=setTimeout(function(){document.getElementById(sa).style.display='none'},12000);
clearTimeout();
}
</script>
</body>
</html>
1.其中style为自定义滚动条的样式。
2.body中的id是动态写入的id,稍后会使用
id="content"
3.<script>内为与qt交互的函数,主要为响应一些点击事件等。以一个函数为例
电脑
function sendToRcv(a,aa){ //函数名称,在html中点击调用
window.mywebkit.onHtmlCall(a,aa); //此为qt与html交互函数,两个参数a代表id唯一标识;aa为状态,根据此状态做相应处理
}
二、qt中主要与html交互的头文件和源文件,首先看头文件
#ifndef QCHATINFOEDIT
#define QCHATINFOEDIT
#include <QObject>
#include <QWidget>
#include "custom/basewidget.h"
#include "widgets/msg.h"
#include <QMap>
#include <QWebView>
#include "custom/loginerrwdg.h"
class QTimer;
class WebView:public QWebView
{
Q_OBJECT
public:
WebView(QWidget *parent=0)
:QWebView(parent)
{
}
virtual ~WebView(){}
signals:
void getMoreMsg();
protected:
//void enterEvent(QEvent *event);
void wheelEvent(QWheelEvent *event);
};
class QChatInfoEdit : public QBaseWidget
{
Q_OBJECT
public:
QChatInfoEdit(QWidget *parent=0);
virtual ~QChatInfoEdit();
public:
void showSendMsg(Msg* msg, bool bStatus=true);
void showRcvMsg(Msg* msg, bool bStatus=true);
// 清屏,不需要向上
void clearScreen();
void setRcv(QString username);
// 清除 msg 映射,不需要向上
void clearMapData();
//显示时间
void showTime(QString strTime,bool bStatus=true);
//显示查看更多消息,不需要向上
void showMore();
//显示查看更多消息load,不需要向上
void showLoad();
void removeLoad();
QString rcvPic(QString id,QString picPath, bool bLeft,bool bStatus, bool bNetWork=true, QString username="");
// 显示绝密通知
QString showSecretNotify(QString picPath, QString contentMsg,bool bStatus);
// 显示通知
void showNotify(QString picPath,QString contentMsg,bool bStatus);
//没有图标
void showNotify(QString contentMsg,bool bStatus);
// 撤销掉之前的显示,不需要向上
void revokeInfoTip(QString strId);
// 显示按钮,不需要向上
void addInfoTip(QString strId);
// 更换占位图,不需要向上
void updatePic(QString strId, QString picPath);
// 文件收发
QString showSendFile(QString fName,QString fSize,int nProcess,QString fId,bool bStatus);
QString showRcvFile(QString fName,QString fSize,int nProcess,QString fId,bool bStatus,QString username="");
// 绝密会话创建
QString secretChatCreate(QString id, int state, QString text,bool bStatus,bool bSelf=false);
QString SecretMsg(QString text, bool bSelf,bool bStatus);
void msgScroll(bool bStatus);
//protected:
// void enterEvent(QEvent *event);
// void wheelEvent(QWheelEvent *event);
signals:
void getMoreMsg();
public slots:
// 更新进度条
void updateProcess(Msg *msg);
// 上传或下载错误
void fileTransferFaile(Msg *msg, bool bStatus=true);
// 文件或者图像传输完毕
void fileTransferFinished(Msg *msg);
public slots: //必须声明为公有的槽函数,才能在html中被调用,以下函数在html中调用
// 点击缩略图获取原图
void onHtmlCallPic(QString strPic);
// 响应绝密会话
void onHtmlCallAcceptSecretChat(QString id, QString strResult);
// 接收文件
void onHtmlCallFile(QString strArvTime, QString strOption);
private slots:
// 向html注册调用名称
void onNotifyAddWindowsObjectToHtml();
private:
// 生成html语句,群组聊天显示联系人名称
QString mucMemMsgName(QString name);
public:
QWebView *m_wviwChat;
private:
LoginErrWdg ErrWdg;
QMap<QString, Msg*> m_data;
QString m_strPathRcv;
QString m_strPathSend;
bool m_bMucMem;
};
#endif // QCHATINFOEDIT
二、qt中主要与html交互的头文件和源文件,首先看源文件
#include "qchatinfoedit.h"
#include <QWebView>
#include <QFile>
#include <QWebFrame>
#include "common/constants.h"
#include "common/emotiondef.h"
#include <QHBoxLayout>
#include <qdebug.h>
#include "log4qt/logrecord.h"
#include "ftpmgr/filemgr.h"
#include "widgets/department.h"
#include "topsecretmgr/topsecretmgr.h"
#include "common/gdfun.h"
extern QString gs_user;
extern QString gs_dns_str;
QChatInfoEdit::QChatInfoEdit(QWidget *parent) : QBaseWidget(parent)
{
m_wviwChat = new WebView(this);
m_borderSize = 1;
setBkCol(QColor("#f8f9fb"), QColor("#f8f9fb"));
setPainterSide(false,true,false,false);
m_wviwChat->settings()->setAttribute(QWebSettings::PluginsEnabled,true);
m_wviwChat->settings()->setAttribute(QWebSettings::JavaEnabled,true);
m_wviwChat->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
m_wviwChat->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows,true);
m_wviwChat->settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard,true);
m_wviwChat->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled,true);
m_wviwChat->settings()->setAttribute(QWebSettings::SpatialNavigationEnabled,true);
m_wviwChat->settings()->setAttribute(QWebSettings::LinksIncludedInFocusChain,true);
m_wviwChat->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled,true);
m_wviwChat->settings()->setAttribute(QWebSettings::AutoLoadImages,true);
//m_wviwChat->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled,true);
m_wviwChat->page()->setForwardUnsupportedContent(true);
m_wviwChat->setContextMenuPolicy (Qt::NoContextMenu);
connect(m_wviwChat->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
this, SLOT(onNotifyAddWindowsObjectToHtml()));
connect(m_wviwChat, SIGNAL(getMoreMsg()),
this, SIGNAL(getMoreMsg()));
QFile source(":/style-new.html");
source.open(QIODevice::ReadOnly);
m_wviwChat->setHtml(QString::fromUtf8(source.readAll().constData()));
source.close();
QHBoxLayout *mainlayout = new QHBoxLayout(this);
mainlayout->addWidget(m_wviwChat);
this->setLayout(mainlayout);
m_data.clear();
//m_wviwChat->setFixedSize(this->size());
}
QChatInfoEdit::~QChatInfoEdit()
{
m_wviwChat->stop();
m_wviwChat->close();
m_wviwChat->deleteLater();
_DELEOBJECT(m_wviwChat)
}
void WebView::wheelEvent(QWheelEvent *event)
{
int j = this->page()->mainFrame()->scrollBarValue(Qt::Vertical);
if(event->orientation()==Qt::Vertical&&event->delta()>0)
if( this->page()->mainFrame()->scrollBarMinimum(Qt::Vertical)==this->page()->mainFrame()->scrollBarValue(Qt::Vertical))
{
emit getMoreMsg();
}
QWebView::wheelEvent(event);
}
void QChatInfoEdit::showSendMsg(Msg* msg, bool bStatus)
{
if (NULL == msg)
{
WriteLog("发送端收到空消息");
return;
}
QString html = QString("");
do
{
// 如果是文本消息
if (Msg::MsgType::text == msg->m_type)
{
QString netStatus = (TextMsgState::NetNormal == msg->m_state) ? "none" : "block";
QString chat = msg->content();
chat.replace("&", "&");
chat.replace("\"", """);
chat.replace(">", ">");
chat.replace("<", "<");
chat.replace("\\", "\\\\");
chat.replace("\n", "<br//>");
chat.replace(" ", " ");
QString strChat = EmotionDef::getInstance()->defToFormat(chat);
html.append(QString("document.getElementById(\"content\").insertAdjacentHTML(\"%4\",\""
"<div style='overflow:hidden;font-family:microsoft yahei ui,microsoft yahei;line-height:21px;font-size: 13px; color:#232323;'>"
"<div style='float: left;width: 100%; padding-top: 5px;padding-bottom: 5px; margin-top: 5px; margin-bottom: 5px;'>"
"<img src='file:///%2' style='width:46px;height:46px;border-radius:50%;border:1px solid #f2f2f2;overflow: hidden;margin-left: 20px; margin-right: 20px; float:right;'>"
"<div style='float: right;position: relative; margin-right: 5px;padding: 6px 13px; max-width:50%; min-height: 21px; border-radius: 5px; border: 1px solid #9ee45f; background-color: #9ee45f;'>"
"<div style='position:absolute;right:-16px;top:10px;width:0;height:0;font-size:0;border:solid 8px;border-color:transparent transparent transparent #9ee45f;'>"
"<div style='position:absolute;right:-6px;top:-7px;width:0;height:0;font-size:0;border:solid 7px;border-color:transparent transparent transparent #9ee45f;'></div>"
"</div>"
"<span style='line-height:21px;word-break:break-all;font-size: 13px;color:#232323;'>%1</span>"
"<div style='display:%3;position:absolute;left:-41px;bottom:6px;width:26px;height:22px;border-radius:50%;background-color:#ff5b5b;text-align:center;color:#fff;padding-top:4px;'>!</div>"
"</div>"
"</div>"
"</div>\")")
.arg(strChat)
.arg(m_strPathSend)
.arg(netStatus)
.arg(bStatus ? "beforeEnd" : "afterBegin"));
break;
}
if (Msg::MsgType::file == msg->m_type)
{
FileMsg *file = NULL;
file = dynamic_cast<FileMsg *>(msg);
if (NULL != file && (FileState::Uploading == file->m_state || FileState::UploadFinished == file->m_state))
{
WriteLog(QString("showsendmsg %1").arg(file->m_state));
html = showSendFile(file->m_fileName,
file->getSize(),
FileState::UploadFinished == file->m_state ? 100 : 0,
QString::number((int)msg),
bStatus);
}
else if (NULL != file && (FileState::UploadCancle == file->m_state))
{
// 取消文件发送
showNotify(FILE_TRANSFER_CANCEL, file->errorDescription(),bStatus);
}
else
{
// 文件发送过程中产生错误
showNotify(FILE_TRANSFER_FAILE, file->errorDescription(),bStatus);
}
break;
}
if (Msg::MsgType::image == msg->m_type)
{
ImageMsg *img = NULL;
img = dynamic_cast<ImageMsg *>(msg);
if (NULL != img && FileState::UploadSpace == img->m_state)//+ "/" + img->m_strFileName
html = rcvPic(QString::number((int)msg),img->m_localThumbPath, false, bStatus, true);
else if(NULL != img && FileState::UploadMin == img->m_state)
showNotify(FILE_TRANSFER_CANCEL, img->errorDescription(),bStatus);
else if(NULL != img && FileState::NetImgError == img->m_state)
html = rcvPic(QString::number((int)msg),img->m_localThumbPath, false, bStatus, false);
else
{