开发环境:
VS2015+Qt5.9
CEF全称是Chromium Embedded Framework,它是Chromium的Content API的封装库,基于Google Chromium 的开源项目,而Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持
主要组成分为
Chromium:基础,网络堆栈,线程,消息机制,log,进程控制,生成Web browser。
WebKit:提供DOM解析,布局,事件处理,渲染,HTML5JS的API。
V8:JS引擎。
Skia:2D图形库。
Angle:3D图形转换,和DirectX有关。
目前CEF分为CEF1,CEF2,CEF3,其中前者使用的是单进程架构,后两者是多进程架构。
在开发使用中一般都是基于CEF3开发。
CEF3是基于Chomuim Content API多进程构架的下一代CEF,拥有下列优势:
1.改进的性能和稳定性(JavaScript和插件在一个独立的进程内执行)。
2.支持Retina显示器。
3.支持WebGL和3D CSS的GPU加速。
4.类似WebRTC和语音输入这样的前卫特性。
5.通过DevTools远程调试协议以及ChromeDriver2提供更好的自动化UI测试。
6.更快获得当前以及未来的Web特性和标准的能力。
单一执行体(Single Executable)
以windows平台为例子
在使用CEF3的时候,需要在主进程中启动CEF
CefEnableHighDPISupport();
//入口函数(Entry-Point Function)
HINSTANCE hInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
CefMainArgs main_args(hInstance);
void* sandbox_info = nullptr; //沙盒信息为空
CefRefPtr<MyRenderProcessHandler> app(new MyRenderProcessHandler);//处理进程相关的回调。
int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
if (exit_code >= 0) {
// 子流程已经完成,返回
return exit_code;
CefSettings settings;
settings.no_sandbox = true; //关闭沙盒模式
settings.multi_threaded_message_loop = true; //多线程消息循环
settings.log_severity = LOGSEVERITY_DISABLE;//日志
//settings.windowless_rendering_enabled = true; //开启离屏模式
CefInitialize(main_args, settings, app_r, sandbox_info);
//启动CEF消息循环,运行后会阻塞到CefQuitMessageLoop()被唤醒
CefRunMessageLoop();
//关闭CEF
CefShutdown();
CEF3常用类和接口
一:CefClient:回调管理类
CefClient提供访问browser-instance-specific的回调接口,单实例CefClient可以共数任意数量的浏览器进程。
比如处理Browser的生命周期,右键菜单,对话框,通知显示, 拖曳事件,焦点事件,
键盘事件等等。如果没有对某个特定的处理接口进行实现会造成什么影响,请查看
cef_client.h文件中相关说明。
举例代码说明(目前小编用到的开发代码)
class CefBrowserHandler: public QObject,
public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefFocusHandler,
public CefLoadHandler//,
//public CefRenderHandler //离屏渲染(关于离屏渲染,后续介绍)
Q_OBJECT
public:
CefBrowserHandler();
public:
// CefClient methods:
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE { return this;}
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE { return this;}
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE { return this; }
virtual CefRefPtr<CefFocusHandler> GetFocusHandler() OVERRIDE { return this; }
//virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE { return this; }
// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
const CefString& target_frame_name,
WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
bool* no_javascript_access)OVERRIDE;
//用来发送一些网页处理的信号
// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,bool isLoading,bool canGoBack,bool canGoForward) OVERRIDE;
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, TransitionType transition_type) OVERRIDE;
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode) OVERRIDE;
// CefFocusHandler methods:
virtual void OnGotFocus(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message);
// Member accessors.
void CloseAllBrowsers(bool forceClose);
CefRefPtr<CefBrowser> GetBrower() { return m_Browser; }
bool IsClosing() { return m_bIsClosing; }
// CefRenderHandler methods:
/*virtual bool GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) OVERRIDE;
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width,
int height) OVERRIDE;
virtual bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) OVERRIDE;
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CursorType type,
const CefCursorInfo& custom_cursor_info) OVERRIDE;*/
signals:
void loadStarted();
void loadFinished(bool loadSuccess);
void browserCreated();
void urlChanged(const QString& url);
void titleChanged(const QString& title);
void loadingStateChanged(bool isLoading, bool canGoBack, bool canGoForward);
void webViewGotFocus();
void recvRenderMsg(const QString& msg);
private:
CefRefPtr<CefBrowser> m_Browser;
int m_BrowserId;
int m_BrowserCount;
bool m_bIsClosing;
typedef std::list<CefRefPtr<CefBrowser>> BrowserList;
BrowserList _browserList;
IMPLEMENT_REFCOUNTING(CefBrowserHandler);
IMPLEMENT_LOCKING(CefBrowserHandler);
1.Browser的生命周期从执行 CefBrowserHost::CreateBrowser() 或者CefBrowserHost::CreateBrowserSync()开始
创建代码,以windows平台为例子
//自定义此结构体来管理浏览器行为
CefBrowserSettings cSettings;
cSettings.file_access_from_file_urls = STATE_ENABLED; //url文件能否访问其他url文件
cSettings.universal_access_from_file_urls = STATE_ENABLED; //url文件能否访问所有url
cSettings.javascript_access_clipboard = STATE_ENABLED; //js是否可以访问剪贴板
cSettings.plugins = STATE_DISABLED; //是否加载插件
//cSettings.windowless_frame_rate = 60; //设置帧率,默认值是30
//根据窗口id来确定浏览器渲染位置
CefWindowInfo info;
CefWindowHandle hWnd = (CefWindowHandle)this->winId();
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = this->width()*qApp->devicePixelRatio();
rect.bottom = this->height()*qApp->devicePixelRatio();
info.SetAsChild(hWnd, rect);
QString url = "www.baidu.com";
//初始化CefClient子类,其中CefLifeSpanHandler类提供了管理Browser生命周期所必需的回调
CefRefPtr<CefBrowserHandler> browserHandler = GetBrowserHandler(browserHandlerIndex);
//创建浏览器
CefBrowserHost::CreateBrowser(info, browserHandler.get(), CefString(url.toStdWString()), _settings, NULL);
2.当Browser对象创建后OnAfterCreated() 方法立即执行,宿主程序可以用这个方法来保持对Browser对象的引用。
void CefBrowserHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
CEF_REQUIRE_UI_THREAD();
//保护成员不受多线程上的访问
AutoLock lock_scope(this);
if (!_browser.get()) {
// 创建浏览器成功后弹出浏览器主窗口
_browser = browser;
_browserId = browser->GetIdentifier();
//发送信号,处理某些业务逻辑
emit browserCreated();
else if (browser->IsPopup()) {
// 如果浏览器窗口已经弹出,加入list,方便后续管理(保证只能在CEF UI线程访问)
_browserList.push_back(browser);
//记录浏览器个数
++_browserCount;
3.Browser的生命周期从执行CefBrowserHost::CloseBrowser()销毁Browser对象结束
Browser对象的关闭事件来源于他的父窗口的关闭方法(比如,在父窗口上点击X控钮。)。父窗口需要调用 CloseBrowser(false) 并且等待操作系统的第二个关闭事件来决定是否允许关闭。
void CefBrowserHandler::CloseAllBrowsers(bool forceClose)
qInfo() << "CloseAllBrowsers::" << __FUNCTION__;
if (!CefCurrentlyOn(TID_UI)) {
// 在UI线程中执行
CefPostTask(TID_UI, base::Bind(&CefBrowserHandler::CloseAllBrowsers, this, forceClose));
return;
if (_browser == NULL)
return;
if (!_browserList.empty()) {
//关闭浏览器列表存在的浏览器
BrowserList::const_iterator it = _browserList.begin();
for (; it != _browserList.end(); ++it)
(*it)->GetHost()->CloseBrowser(forceClose);
return;
if (_browser.get()) {
// 请求关闭浏览器
_browser->GetHost()->CloseBrowser(forceClose);
DoClose方法设置m_blsClosing 标志位为true,并返回false以再次发送操作系统的关闭事件。
bool CefBrowserHandler::DoClose(CefRefPtr<CefBrowser> browser)
qInfo() << "DoClose::" << __FUNCTION__;
CEF_REQUIRE_UI_THREAD();
//保护成员不受多线程上的访问
AutoLock lock_scope(this);
if (browser->GetIdentifier() == _browserId) {
_isClosing = true;
//再次发送操作系统的关闭事件
return false;
当操作系统捕捉到第二次关闭事件,它才会允许父窗口真正关闭。该动作会先触发OnBeforeClose()回调,请在该回调里释放所有对浏览器对象的引用
void CefBrowserHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
qInfo() << "OnBeforeClose::" << __FUNCTION__;
CEF_REQUIRE_UI_THREAD();
//保护成员不受多线程上的访问
AutoLock lock_scope(this);
if (_browserId == browser->GetIdentifier()) {
_browser = nullptr;
else if (browser->IsPopup()) {
//清空浏览器列表并关闭销毁浏览器对象
BrowserList::iterator bit = _browserList.begin();
for (; bit != _browserList.end(); ++bit) {
if ((*bit)->IsSame(browser)) {
_browserList.erase(bit);
break;
if (--_browserCount == 0) {
// 当所有浏览器窗口已关闭退出时应用程序消息循环.
CefQuitMessageLoop();
二:CefApp
CefApp接口提供了不同进程的可定制回调函数,包含与进程,命令行参数,代理,资源管理相关的回调类,一些功能是由所有进程共享的,有些必须实现浏览器的过程中,必须在渲染过程中执行,可以让开发者定制属于自己的逻辑。
其中重要的回调函数如下:
1.OnBeforeCommandLineProcessing 提供了以编程方式设置命令行参数的机会。
2.OnRegisterCustomSchemes 提供了注册自定义schemes的机会。
3.CefBrowserProcessHandler 返回定制Browser进程的Handler,该Handler包括了OnContextInitialized这样的回调。
4.CefRenderProcessHandler 返回定制Render进程的Handler,该Handler包含了JavaScript相关的一些回调以及消息处理的回调。
举例代码说明(小编所用到的回调类)
//CefBrowserProcessHandler
class CefAppHandler : public CefApp,
public CefBrowserProcessHandler
public:
CefAppHandler();
public:
// CefApp methods:
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE {
return this;
private:
IMPLEMENT_REFCOUNTING(CefAppHandler);
//CefRenderProcessHandler
class MyRenderProcessHandler :public CefApp,
public CefRenderProcessHandler
public:
MyRenderProcessHandler();
CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE
return this;
void OnContextCreated(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context);
private:
IMPLEMENT_REFCOUNTING(MyRenderProcessHandler);
详细定制逻辑功能不详说了,因功能而异实现对应逻辑。
三:CefBrowser和CefFrame
CefBrowser管理renderer进程中执行浏览相关的类,包括网页前进后退,历史导航,加载字符串和请求,发送编辑命令,提取text/html内容,来源检索,加载请求等。
CefFrame用于加载特定url,在该运行环境下执行JavaScript代码等。
CefBrowser和CefFrame对象被用来发送命令给浏览器以及在回调函数里获取状态信息。每个CefBrowser对象包含一个主CefFrame对象,主CefFrame对象代表页面的顶层frame。
同时每个CefBrowser对象可以包含零个或多个的CefFrame对象,分别代表不同的子Frame,例如,一个浏览器加载了两个iframe,则该CefBrowser对象拥有三个CefFrame对象(顶层frame和两个iframe)。
常见的网页操作举例代码如下:
//在浏览器的主frame加载一个特定url
browser->GetMainFrame()->LoadURL("www.baidu.com");
//浏览器页面回退
browser->GoBack();
//浏览器页面向前
browser->GoForward();
//浏览器页面刷新
browser->Reload();
//浏览器页面停止
browser->StopLoad();
//浏览器窗口的原生句柄
CefWindowHandle window_handle = browser->GetHost()->GetWindowHandle();
//从主frame里获取HTML内容
class Visitor : public CefStringVisitor
public:
Visitor() {}
virtual void Visit(const CefString& string) OVERRIDE {
// xxx(); 某些逻辑操作
IMPLEMENT_REFCOUNTING(Visitor);
browser->GetMainFrame()->GetSource(new Visitor());
四:V8引擎
v8 引擎用于高效解析和执行 JavaScript。
v8 引擎设计了高效的垃圾回收机制,以保证快速的对象内存分配、短暂的垃圾回收暂停、无内存碎片。
CEF3提供支持V8Extension的接口,但是这有两个限制
第一,v8 extension仅在Renderer进程使用。
第二,仅在沙箱模型关闭时使用。
V8引擎的功能比较多,目前小编只用到了CefV8Handler类与JavaScript交互功能
CefV8Handler 是一个纯接口类,只有一个方法,你可以继承它,并提供相应的实现
class MyV8Handler :public CefV8Handler
public:
MyV8Handler();
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE;
void SendMsgToBrowser(CefString str);
public:
IMPLEMENT_REFCOUNTING(MyV8Handler);
//与js进行通信交互,还需要用到CefV8Context类和CEF 类型:CefV8Value
CefRefPtr<CefV8Context> context
CefRefPtr<CefV8Value> object = context->GetGlobal();
// 创建MyV8Handler对象
CefRefPtr<MyV8Handler> handler = new MyV8Handler();
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("ReceivedMsgFromJS", handler);
object->SetValue("ReceivedMsgFromJS", func, V8_PROPERTY_ATTRIBUTE_NONE);
//发送消息
void QCefWebView::SendMsgToPage(const QString &msg)
CefRefPtr<CefFrame> frame =GetBrowser(browserHandlerIndex)->GetMainFrame();
QString datastr;
datastr="SigSendMessageToJS('";
datastr+=msg;
datastr+="')";
CefString code;
code.FromString(datastr.toStdString());
frame->ExecuteJavaScript(code, frame->GetURL(), 0);
bool MyV8Handler::Execute(const CefString &name, CefRefPtr<CefV8Value> object, const CefV8ValueList &arguments, CefRefPtr<CefV8Value> &retval, CefString &exception)
if (name == "ReceivedMsgFromJS") {
if (arguments.size() == 1) {
CefString strFromWeb = arguments.at(0)->GetStringValue();
std::string stdstr=strFromWeb.ToString();
QString str=QString::fromLocal8Bit(strFromWeb.ToString().c_str());
SendMsgToBrowser(strFromWeb);
retval = CefV8Value::CreateString(strFromWeb);
else {
retval = CefV8Value::CreateInt(0);
return true;
return false;
void MyV8Handler::SendMsgToBrowser(CefString str)
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("vvMsg");
CefRefPtr<CefListValue> args = msg->GetArgumentList();
args->SetSize(1);
args->SetString(0, str);
CefV8Context::GetCurrentContext()->GetBrowser()->SendProcessMessage(PID_BROWSER, msg);
//接收消息
//OnProcessMessageReceived在Render进程收到进程间消息时被调用
bool CefBrowserHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
const std::string& messageName = message->GetName();
if (messageName == "vvMsg") //messageName要和MyV8Handler类SendMsgToBrowser函数中定义的一样
CefRefPtr<CefListValue> args = message->GetArgumentList();
CefString string0 = args->GetString(0);
// QString res=QString::fromLocal8Bit(string0.ToString().c_str()); 中文会乱码
QString res = QString::fromStdWString(string0.c_str());
emit recvRenderMsg(res);
return true;
return false;
五:其他类
常见的都在以上代码中已定义,其他的可以查询文档详解,不例举了。
CEF官方文档
目前还在深入研究学习CEF,文章有诸多漏洞,望见谅,望指正,感谢~
CEF官网地址
CEF官方论坛
参考文档:https://github.com/fanfeilong/cefutil/blob/master/doc/CEF%20General%20Usage-zh-cn.md#off-screen-rendering
内附小编浏览器效果
完整项目工程地址:GitHub
关于CEFCEF全称是Chromium Embedded Framework,它是Chromium的Content API的封装库,基于Google Chromium 的开源项目,而Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持主要组成分为Chromium:基础,网络堆栈,线程,消息机制,log,进程控制,生成Web browser。WebKit:提供DOM解析,布局,事件处理,渲染,HTML5JS的API。V8:
cef支持跨平台,是基于Chromium的开源浏览器控件,全称Chromium Embedded Framework。
本文主要介绍如何下载cef以及编译windows下的cef项目,并运行查看浏览器显示效果。
QT内嵌CEF优势:
Qt自带QWebEngine模块,可以快速实现浏览器,但是在实际使用中,在某些AMD显卡电脑运行使用了QWebEngine的qt软件,
会卡顿甚至奔溃,坑还是比较多的。选择cef就可以避免这种问题。
开发准备
cef下载网址:http://opensource.sp
在Windows上运行构建脚本之前,您必须具有先决条件:
在PATH上安装了w / qmake.exe最新Qt(5.x)
在PATH上使用cmake.exe安装的最新CMake
在PATH上安装有python.exe最新Python(2.x)
在PATH上安装了最新的Go(带有go.exe
安装了并执行以下操作,以将64位VC编译器放在PATH : "C:\Program Files (x86)\Microsoft Visual S
首先先说说QtWebkit、QtWebEngine、QAxWidget三种方式显示网页的应用场景
QtWebkit:在Qt5.6以前,都是使用QtWebkit组件,但Qt5.6以后,移除了QtWebkit这个组件
QtWebEngine:Qt5.6以后的MSVC版本,引进了基于Chromium的浏览器引擎 QtWebEngine
QAxWidget:Qt5.6以后的mingw版本,由于移除了QtW...
首先重载QComboBox,因为想保持下拉框与QComboBox控件间隔,就需要重载QComboBox的showPopup。
void vComboBox::showPopup()
emit sigPopup();
QComboBox::showPopup();
QWidget *popup = this->findChild<QFrame*>();
popup-...
Qt和CEF可以实现混合开发,即将两种技术和优点结合起来,开发出高效、高可靠性的应用程序。下面我们来看一个Qt CEF混合开发应用实例。
以开发一个简单的浏览器为例,首先使用Qt的QtWebEngine模块创建浏览器框架,然后使用CEF库来加载HTML页面。具体步骤如下:
1.创建Qt浏览器框架:使用QtWebEngine模块创建一个基本的浏览器窗口,该窗口可以包含地址栏、前进/后退、刷新等基本浏览器功能。
2.集成CEF:将CEF库与Qt框架集成。CEF库是一个基于Chromium开发的框架,可以用于加载HTML、JavaScript、CSS等Web技术。CEF库提供了强大的JavaScript和UI交互能力,可以通过CEF实现更多更复杂的功能。
3.在Qt中使用CEF:通过Qt的QWindow类和CEF的CefWindowHandle类实现QWindow和CEF窗口之间的交互。可以使用Qt的信号/槽机制来处理CEF窗口的事件。
4.加载HTML页面:通过CEF加载HTML页面,通过Qt的WebView控件在浏览器框架中显示页面内容。
通过以上步骤,我们可以创建一个基于Qt和CEF混合开发的浏览器应用程序。这种混合开发方式可以充分利用Qt和CEF提供的各自的优势,开发出高效、高可靠性的应用程序。同时也可以在UI和交互方面更加灵活地实现各种功能。
### 回答2:
Qt和CEF(Chromium Embedded Framework)混合开发应用可以使你开发跨平台的、具有Web前端组件的应用,为用户提供更好的用户体验和更丰富的交互特性,下面是一个实例。
我们可以使用Qt作为应用程序框架,同时使用CEF作为嵌入的Web浏览器来呈现Web内容。这个应用程序使用了Qt的GUI组件、CEF的Web组件和C++的普通类和函数来实现。
具体实现过程如下:
1. 下载和安装CEF。CEF是一个本地Web浏览器框架,支持Windows、macOS和Linux系统。它允许你使用Chromium浏览器内核来呈现Web内容。CEF提供了一系列的API和工具来支持应用与Web内容直接的交互。
2. 使用Qt Creator创建一个新的Qt Widgets应用程序。在项目设置中配置如下:
a. 加入CEF运行时库文件和头文件。
b. 对于Windows平台,在项目属性中配置Qt和CEF的链接库。
c. 添加一个Qt Form作为主界面。
3. 在Qt代码中使用CEF组件,在主界面中添加一个QVBoxLayout。将CEF Widget直接放在这个Layout中,从而实现与其他Qt Widgets的混合。
4. 在C++代码中创建一个CEF浏览器对象。这个对象负责加载和解析Web页面,和处理浏览器事件。在开始时CEF浏览器会调用on_loading_state_change()回调函数,它表示CEF正在加载Web页面。
5. 当CEF浏览器加载Web页面时,处理web页面中的事件,例如提交表单、点击按钮等。CEF JavaScript Binding桥接机制可以让你在C++代码中注册JavaScript回调,让Web侧能够调用本地功能。CEF也允许你从Web页面中注入JavaScript脚本,以实现与本地代码的通信。
总结:使用Qt和CEF混合开发应用,可以开发出具有极佳用户体验的跨平台应用程序,一方面,可以充分利用CEF提供的强大的Web交互能力,另一方面,可以使用Qt的GUI组件来构建应用程序框架,并使其与Web组件混合。对于开发者而言,这意味着更轻松的应用程序开发和更高效的应用程序交互方式。
### 回答3:
qt和cef的混合开发应用是通过将QT的界面与CEF的web浏览器引擎相结合,实现了一种可支持Web技术的应用程序的开发方式。
比如在一个桌面应用程序中,用户可以在QT界面中使用CEF作为内置浏览器来浏览Web页面或连接Web服务。
一种实例是使用QT中的QWebEngineView来加载CEF中的Web页面,可以通过QWebChannel来实现QT和CEF两者之间的通信,例如把QT中的JavaScript对象传递到CEF中,或者把CEF中的事件传递到QT中进行处理。这样可以实现在QT应用程序中嵌入Web浏览器,同时利用QT的强大框架和CEF的强大Web渲染技术为应用程序添加更多的功能。
另外,QT中还提供了QtWebEngineWidgets来支持类似于CEF的Web浏览器功能,同时可以与QT的界面框架无缝整合,用于创建具有丰富Web功能的桌面应用程序。
总之,QT和CEF的混合开发应用可以扩展应用程序的Web功能,从而提供更加丰富、更加强大的用户体验。
windows启动时出现:THE SYSTEM FOUND UNAUTHORIZED CHANGES ON THE FIRMWARE,OPERATIONG SYSTEM OR UEFI DRIVERS
80836
docker启动时出现Job for docker.service failed because the control process exited with error code错误
62324
windows启动时出现:THE SYSTEM FOUND UNAUTHORIZED CHANGES ON THE FIRMWARE,OPERATIONG SYSTEM OR UEFI DRIVERS
2301_81732128:
基于Qt仿QQ效果实现图片查看器(支持查看GIF)
qq_14827935:
基于Qt仿QQ效果实现图片查看器(支持查看GIF)
printf/fprintf在终端输出带颜色的数据
m0_74415145:
Windows下安装ninja环境
AP840: