# Example of embedding CEF browser using PyQt/PySide libraries.
# This example has two widgets: a navigation bar and a browser.
#
# Tested configurations:
# - PyQt 4.11 (qt 4.8) on Windows/Linux
# - PySide 1.2 (qt 4.8) on Windows/Linux/Mac
# - CEF Python v55.4+
#
# Issues on Mac (tested with PySide):
# - Keyboard focus issues when switching between controls (Issue #284)
# - Mouse cursor never changes when hovering over links (Issue #311)
# - Sometimes process hangs when quitting app
from cefpython3 import cefpython as cef
import ctypes
import os
import platform
import sys
# PyQt imports
if "pyqt" in sys.argv:
# noinspection PyUnresolvedReferences
from PyQt4.QtGui import *
# noinspection PyUnresolvedReferences
from PyQt4.QtCore import *
# PySide imports
elif "pyside" in sys.argv:
# noinspection PyUnresolvedReferences
import PySide
# noinspection PyUnresolvedReferences
from PySide import QtCore
# noinspection PyUnresolvedReferences
from PySide.QtGui import *
# noinspection PyUnresolvedReferences
from PySide.QtCore import *
else:
print("USAGE:")
print(" qt4.py pyqt")
print(" qt4.py pyside")
sys.exit(1)
# Fix for PyCharm hints warnings when using static methods
WindowUtils = cef.WindowUtils()
# Platforms
WINDOWS = (platform.system() == "Windows")
LINUX = (platform.system() == "Linux")
MAC = (platform.system() == "Darwin")
# Configuration
WIDTH = 800
HEIGHT = 600
# OS differences
CefWidgetParent = QWidget
if LINUX:
# noinspection PyUnresolvedReferences
CefWidgetParent = QX11EmbedContainer
def main():
check_versions()
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
cef.Initialize()
app = CefApplication(sys.argv)
main_window = MainWindow()
main_window.show()
main_window.activateWindow()
main_window.raise_()
app.exec_()
app.stopTimer()
del main_window # Just to be safe, similarly to "del app"
del app # Must destroy app object before calling Shutdown
cef.Shutdown()
def check_versions():
print("[qt4.py] CEF Python {ver}".format(ver=cef.__version__))
print("[qt4.py] Python {ver} {arch}".format(
ver=platform.python_version(), arch=platform.architecture()[0]))
# PyQt version
if "pyqt" in sys.argv:
# noinspection PyUnresolvedReferences
print("[qt4.py] PyQt {v1} (qt {v2})".format(
v1=PYQT_VERSION_STR, v2=qVersion()))
# PySide version
elif "pyside" in sys.argv:
print("[qt4.py] PySide {v1} (qt {v2})".format(
v1=PySide.__version__, v2=QtCore.__version__))
# CEF Python version requirement
assert cef.__version__ >= "55.4", "CEF Python v55.+ required to run this"
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__(None)
self.cef_widget = None
self.navigation_bar = None
if "pyqt" in sys.argv:
self.setWindowTitle("PyQt example")
elif "pyside" in sys.argv:
self.setWindowTitle("PySide example")
self.setFocusPolicy(Qt.StrongFocus)
self.setupLayout()
def setupLayout(self):
self.resize(WIDTH, HEIGHT)
self.cef_widget = CefWidget(self)
self.navigation_bar = NavigationBar(self.cef_widget)
layout = QGridLayout()
layout.addWidget(self.navigation_bar, 0, 0)
layout.addWidget(self.cef_widget, 1, 0)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
layout.setRowStretch(0, 0)
layout.setRowStretch(1, 1)
frame = QFrame()
frame.setLayout(layout)
self.setCentralWidget(frame)
# Browser can be embedded only after layout was set up
self.cef_widget.embedBrowser()
def closeEvent(self, event):
# Close browser (force=True) and free CEF reference
if self.cef_widget.browser:
self.cef_widget.browser.CloseBrowser(True)
self.clear_browser_references()
def clear_browser_references(self):
# Clear browser references that you keep anywhere in your
# code. All references must be cleared for CEF to shutdown cleanly.
self.cef_widget.browser = None
class CefWidget(CefWidgetParent):
def __init__(self, parent=None):
super(CefWidget, self).__init__(parent)
self.parent = parent
self.browser = None
self.show()
def focusInEvent(self, event):
# This event seems to never get called on Linux, as CEF is
# stealing all focus due to Issue #284.
if self.browser:
if WINDOWS:
WindowUtils.OnSetFocus(self.getHandle(), 0, 0, 0)
self.browser.SetFocus(True)
def focusOutEvent(self, event):
# This event seems to never get called on Linux, as CEF is
# stealing all focus due to Issue #284.
if self.browser:
self.browser.SetFocus(False)
def embedBrowser(self):
window_info = cef.WindowInfo()
rect = [0, 0, self.width(), self.height()]
window_info.SetAsChild(self.getHandle(), rect)
self.browser = cef.CreateBrowserSync(window_info,
url="https://www.google.com/")
self.browser.SetClientHandler(LoadHandler(self.parent.navigation_bar))
self.browser.SetClientHandler(FocusHandler(self))
def getHandle(self):
# PySide bug: QWidget.winId() returns