# Example of embedding CEF Python browser using PyQt/PySide libraries.
# This example has two widgets: a navigation bar and a browser.
#
# Tested configurations:
# - PyQt 4.11.4 (4.8.7) on Windows
# - PySide 1.2.4 (4.8.7) on Windows
# - PyQt 4.10.4 (4.8.6) on Linux
# - PySide 1.2.1 (4.8.6) on Linux
# - CEF Python v55.4+
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(" qt.py pyqt")
print(" qt.py pyside")
sys.exit(1)
# Fix for PyCharm hints warnings
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()
app.exec_()
app.stopTimer()
del main_window # Just to be safe, see below
del app # Must destroy before calling Shutdown
cef.Shutdown()
def check_versions():
print("[qt.py] CEF Python {ver}".format(ver=cef.__version__))
print("[qt.py] Python {ver}".format(ver=sys.version[:6]))
# PyQt version
if "pyqt" in sys.argv:
# noinspection PyUnresolvedReferences
print("[qt.py] PyQt {v1} ({v2})".format(
v1=PYQT_VERSION_STR, v2=qVersion()))
# PySide version
elif "pyside" in sys.argv:
print("[qt.py] PySide {v1} ({v2})".format(
v1=PySide.__version__, v2=QtCore.__version__))
# CEF Python version requirement
assert cef.__version__ >= "55.3", "CEF Python v55.3+ 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 focusInEvent(self, event):
# This event seems to never get called on Linux, as CEF is
# stealing all focus due to Issue #284.
# print("[qt.py] focusInEvent")
if self.cef_widget.browser:
if WINDOWS:
WindowUtils.OnSetFocus(self.cef_widget.getHandle(),
0, 0, 0)
self.cef_widget.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.
# print("[qt.py] focusOutEvent")
pass
def closeEvent(self, event):
# Close browser (force=True) and free CEF reference
if self.cef_widget.browser:
self.cef_widget.browser.CloseBrowser(True)
self.cef_widget.browser = None # free ref
class NavigationBar(QFrame):
def __init__(self, cef_widget):
super(NavigationBar, self).__init__()
self.cef_widget = cef_widget
# Init layout
layout = QGridLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# Back button
self.back = self.createButton("back")
# noinspection PyUnresolvedReferences
self.back.clicked.connect(self.onBack)
layout.addWidget(self.back, 0, 0)
# Forward button
self.forward = self.createButton("forward")
# noinspection PyUnresolvedReferences
self.forward.clicked.connect(self.onForward)
layout.addWidget(self.forward, 0, 1)
# Reload button
self.reload = self.createButton("reload")
# noinspection PyUnresolvedReferences
self.reload.clicked.connect(self.onReload)
layout.addWidget(self.reload, 0, 2)
# Url input
self.url = QLineEdit("")
# noinspection PyUnresolvedReferences
self.url.returnPressed.connect(self.onGoUrl)
layout.addWidget(self.url, 0, 3)
# Layout
self.setLayout(layout)
self.updateState()
def onBack(self):
if self.cef_widget.browser:
self.cef_widget.browser.GoBack()
def onForward(self):
if self.cef_widget.browser:
self.cef_widget.browser.GoForward()
def onReload(self):
if self.cef_widget.browser:
self.cef_widget.browser.Reload()
def onGoUrl(self):
if self.cef_widget.browser:
self.cef_widget.browser.LoadUrl(self.url.text())
def updateState(self):
browser = self.cef_widget.browser
if not browser:
self.back.setEnabled(False)
self.forward.setEnabled(False)
self.reload.setEnabled(False)
self.url.setEnabled(False)
return
self.back.setEnabled(browser.CanGoBack())
self.forward.setEnabled(browser.CanGoForward())
self.reload.setEnabled(True)
self.url.setEnabled(True)
self.url.setText(browser.GetUrl())
def createButton(self, name):
resources = os.path.join(os.path.abspath(os.path.dirname(__file__)),
"resources")
pixmap = QPixmap(os.path.join(resources, "{0}.png".format(name)))
icon = QIcon(pixmap)
button = QPushButton()
button.setIcon(icon)
button.setIconSize(pixmap.rect().size())
return button
class CefWidget(CefWidgetParent):
def __init__(self, parent=None):
super(CefWidget, self).__init__(parent)
self.parent = parent
self.browser = None
self.show()
def embedBrowser(self):
self.width = 0
self.height = 0
window_info = cef.WindowInfo()
window_info.SetAsChild(self.getHandle())
self.browser = cef.CreateBrowserSync(window_info,
url="https://www.google.com/")
self.browser.SetClientHandler(LoadHandler(self.parent.navigation_bar))
self.browser.SetClientHandler(FocusHandler())
def getHandle(self):
# PySide bug: QWidget.winId() returns