CEFPython 无法嵌入到 pyqt5 应用程序中
CEFPython unable to embed inside pyqt5 application
我是 Cefpython 和 PyQt5 的新手。我试图按照 cefpython 存储库中的教程进行操作。
我试图将 cefpython 嵌入到 pyqt 应用程序中,但没有取得任何成功,这里有什么问题吗?
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QWindow
from PyQt5.QtWidgets import *
from cefpython3 import cefpython as cef
from navbar import NavigationBar
class ChromiumApplication(QApplication):
def __init__(self):
super().__init__([])
self.timer = self.create_timer()
def create_timer(self):
timer = QTimer()
timer.timeout.connect(self.on_timeout)
timer.start(10)
return timer
def on_timeout(self):
cef.MessageLoopWork()
class ChromiumBrowserWindow(QMainWindow):
DEFAULT_TITLE = "Chromium Browser"
DEFAULT_WIDTH = 800
DEFAULT_HEIGHT = 600
def __init__(self):
super().__init__()
self.chrome = None
self.web_view = None
self.setWindowTitle(self.DEFAULT_TITLE)
self.init_window()
self.show()
def init_window(self):
self.resize(self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
self.web_view = WebViewWidget(parent=self)
self.chrome = NavigationBar(parent=self, browser=self.web_view.browser)
layout = QGridLayout()
layout.addWidget(self.chrome, 0, 0)
layout.setColumnStretch(0, 1)
layout.addWidget(self.web_view, 1, 0)
layout.setRowStretch(1, 2)
layout.setContentsMargins(0, 0, 0, 0)
frame = QFrame()
frame.setLayout(layout)
self.setCentralWidget(frame)
self.web_view.init_browser()
def closeEvent(self, event):
if self.web_view.browser is not None:
self.web_view.browser.CloseBrowser(True) # force=True
self.web_view.browser = None # required to close cleanly
class WebViewWidget(QWidget):
DEFAULT_URL = "https://www.google.com"
HANDLERS = []
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.browser = None
self.browser_window = None
self.timer = None
def init_browser(self):
self.browser_window = QWindow()
window_config = cef.WindowInfo()
rect_pos_and_size = [0, 0, self.width(), self.height()]
window_config.SetAsChild(self.get_window_handle(), rect_pos_and_size)
self.browser = cef.CreateBrowserSync(window_config, url=self.DEFAULT_URL)
self.set_handlers()
def get_window_handle(self):
return int(self.browser_window.winId())
def set_handlers(self):
for handler in self.HANDLERS:
self.browser.SetClientHanlder(handler(self))
if __name__ == "__main__":
sys.excepthook = cef.ExceptHook
cef.Initialize()
app = ChromiumApplication()
window = ChromiumBrowserWindow()
app.exec()
app.timer.stop()
cef.Shutdown()
我知道问题出在我的代码上,因为 cefpython 提供的示例在我的机器上运行完美。我不知道我在这里做错了什么,任何建议都会有所帮助!
编辑:(导航栏代码)
from PyQt5.QtWidgets import (
QApplication,
QFrame,
QHBoxLayout,
QPushButton,
QLineEdit,
)
class NavigationBar(QFrame):
def __init__(self, parent=None, browser=None):
super().__init__()
self.parent = parent
self.browser = browser
self.back_btn = self.create_button("Back")
self.back_btn.clicked.connect(self.on_back)
self.forward_btn = self.create_button("Forward")
self.forward_btn.clicked.connect(self.on_forward)
self.refresh_btn = self.create_button("Refresh")
self.refresh_btn.clicked.connect(self.on_refresh)
self.url_bar = self.create_url_bar()
self.url_bar.returnPressed.connect(self.on_search)
self.frame_layout = QHBoxLayout()
self.init_layout()
def create_button(self, name):
button_icon_path = f"./{name}.svg"
button = QPushButton()
button.setStyleSheet(f"""
QPushButton {{
background-image: url("{button_icon_path}");
background-repeat: no-repeat;
background-position: center;
background-color: rgba(0, 0, 0, 0.1);
border: 10px;
border-radius: 8px;
padding: 10px;
}}
QPushButton:hover {{
background-color: rgba(0, 0, 0, 0.5);
}}
QPushButton:pressed {{
background-color: none;
}}
""")
return button
def create_url_bar(self):
search = QLineEdit()
search.setStyleSheet("""QLineEdit {
min-width: 300px;
padding: 10px;
margin-left: 50px;
margin-right: 30px;
border-width: 10px;
border-radius: 8px;
background-color: rgba(0, 0, 0, 0.2);
color: white;
}
QLineEdit:hover {
background-color: #454549;
}
""")
return search
def init_layout(self):
self.setStyleSheet("""
background: #2A292E;
max-height: 40px;
""")
self.frame_layout.addWidget(self.back_btn, 0)
self.frame_layout.addWidget(self.forward_btn, 0)
self.frame_layout.addWidget(self.refresh_btn, 0)
self.frame_layout.addWidget(self.url_bar, 1)
self.setLayout(self.frame_layout)
def on_back(self):
if self.browser is not None:
self.browser.GoBack()
def on_forward(self):
if self.browser is not None:
self.browser.GoForward()
def on_refresh(self):
if self.browser is not None:
self.browser.Reload()
def on_search(self):
if self.browser is not None:
url = self.url_bar.text()
self.browser.LoadUrl(url)
if __name__ == "__main__":
app = QApplication([])
nav = NavigationBar()
nav.show()
app.exec()
问题是用于渲染浏览器的 QWindow
被隐藏了。解决方案是使用 QWidget::createWindowContainer()
创建一个 QWidget 并使用布局添加它。
import sys
from cefpython3 import cefpython as cef
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QWindow
from PyQt5.QtWidgets import QApplication, QFrame, QGridLayout, QMainWindow, QVBoxLayout, QWidget
from navbar import NavigationBar
class ChromiumApplication(QApplication):
def __init__(self):
super().__init__([])
self.timer = self.create_timer()
def create_timer(self):
timer = QTimer()
timer.timeout.connect(self.on_timeout)
timer.start(10)
return timer
def on_timeout(self):
cef.MessageLoopWork()
class ChromiumBrowserWindow(QMainWindow):
DEFAULT_TITLE = "Chromium Browser"
DEFAULT_WIDTH = 800
DEFAULT_HEIGHT = 600
def __init__(self):
super().__init__()
self.chrome = None
self.web_view = None
self.setWindowTitle(self.DEFAULT_TITLE)
self.init_window()
self.show()
def init_window(self):
self.resize(self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
self.web_view = WebViewWidget()
self.chrome = NavigationBar(parent=self, browser=self.web_view.browser)
frame = QFrame()
self.setCentralWidget(frame)
layout = QGridLayout(frame)
layout.addWidget(self.chrome, 0, 0)
layout.setColumnStretch(0, 1)
layout.addWidget(self.web_view, 1, 0)
layout.setRowStretch(1, 2)
layout.setContentsMargins(0, 0, 0, 0)
def closeEvent(self, event):
if self.web_view.browser is not None:
self.web_view.browser.CloseBrowser(True)
del self.web_view.browser
class WebViewWidget(QWidget):
DEFAULT_URL = "https://www.google.com"
HANDLERS = []
def __init__(self, parent=None):
super().__init__(parent)
self._browser = None
self._browser_widget = None
lay = QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
self.init_browser()
@property
def browser(self):
return self._browser
@browser.deleter
def browser(self):
self._browser = None
def init_browser(self):
browser_window = QWindow()
window_config = cef.WindowInfo()
window_config.SetAsChild(
int(browser_window.winId()), list(self.rect().getRect())
)
self._browser = cef.CreateBrowserSync(window_config, url=self.DEFAULT_URL)
self._browser_widget = QWidget.createWindowContainer(browser_window)
self.layout().addWidget(self._browser_widget)
self.set_handlers()
def set_handlers(self):
for handler in self.HANDLERS:
self.browser.SetClientHanlder(handler(self))
def resizeEvent(self, event):
if self.browser and self._browser_widget:
self.browser.SetBounds(*self._browser_widget.geometry().getRect())
self.browser.NotifyMoveOrResizeStarted()
if __name__ == "__main__":
sys.excepthook = cef.ExceptHook
cef.Initialize()
app = ChromiumApplication()
window = ChromiumBrowserWindow()
app.exec()
app.timer.stop()
cef.Shutdown()
我是 Cefpython 和 PyQt5 的新手。我试图按照 cefpython 存储库中的教程进行操作。 我试图将 cefpython 嵌入到 pyqt 应用程序中,但没有取得任何成功,这里有什么问题吗?
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QWindow
from PyQt5.QtWidgets import *
from cefpython3 import cefpython as cef
from navbar import NavigationBar
class ChromiumApplication(QApplication):
def __init__(self):
super().__init__([])
self.timer = self.create_timer()
def create_timer(self):
timer = QTimer()
timer.timeout.connect(self.on_timeout)
timer.start(10)
return timer
def on_timeout(self):
cef.MessageLoopWork()
class ChromiumBrowserWindow(QMainWindow):
DEFAULT_TITLE = "Chromium Browser"
DEFAULT_WIDTH = 800
DEFAULT_HEIGHT = 600
def __init__(self):
super().__init__()
self.chrome = None
self.web_view = None
self.setWindowTitle(self.DEFAULT_TITLE)
self.init_window()
self.show()
def init_window(self):
self.resize(self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
self.web_view = WebViewWidget(parent=self)
self.chrome = NavigationBar(parent=self, browser=self.web_view.browser)
layout = QGridLayout()
layout.addWidget(self.chrome, 0, 0)
layout.setColumnStretch(0, 1)
layout.addWidget(self.web_view, 1, 0)
layout.setRowStretch(1, 2)
layout.setContentsMargins(0, 0, 0, 0)
frame = QFrame()
frame.setLayout(layout)
self.setCentralWidget(frame)
self.web_view.init_browser()
def closeEvent(self, event):
if self.web_view.browser is not None:
self.web_view.browser.CloseBrowser(True) # force=True
self.web_view.browser = None # required to close cleanly
class WebViewWidget(QWidget):
DEFAULT_URL = "https://www.google.com"
HANDLERS = []
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.browser = None
self.browser_window = None
self.timer = None
def init_browser(self):
self.browser_window = QWindow()
window_config = cef.WindowInfo()
rect_pos_and_size = [0, 0, self.width(), self.height()]
window_config.SetAsChild(self.get_window_handle(), rect_pos_and_size)
self.browser = cef.CreateBrowserSync(window_config, url=self.DEFAULT_URL)
self.set_handlers()
def get_window_handle(self):
return int(self.browser_window.winId())
def set_handlers(self):
for handler in self.HANDLERS:
self.browser.SetClientHanlder(handler(self))
if __name__ == "__main__":
sys.excepthook = cef.ExceptHook
cef.Initialize()
app = ChromiumApplication()
window = ChromiumBrowserWindow()
app.exec()
app.timer.stop()
cef.Shutdown()
我知道问题出在我的代码上,因为 cefpython 提供的示例在我的机器上运行完美。我不知道我在这里做错了什么,任何建议都会有所帮助!
编辑:(导航栏代码)
from PyQt5.QtWidgets import (
QApplication,
QFrame,
QHBoxLayout,
QPushButton,
QLineEdit,
)
class NavigationBar(QFrame):
def __init__(self, parent=None, browser=None):
super().__init__()
self.parent = parent
self.browser = browser
self.back_btn = self.create_button("Back")
self.back_btn.clicked.connect(self.on_back)
self.forward_btn = self.create_button("Forward")
self.forward_btn.clicked.connect(self.on_forward)
self.refresh_btn = self.create_button("Refresh")
self.refresh_btn.clicked.connect(self.on_refresh)
self.url_bar = self.create_url_bar()
self.url_bar.returnPressed.connect(self.on_search)
self.frame_layout = QHBoxLayout()
self.init_layout()
def create_button(self, name):
button_icon_path = f"./{name}.svg"
button = QPushButton()
button.setStyleSheet(f"""
QPushButton {{
background-image: url("{button_icon_path}");
background-repeat: no-repeat;
background-position: center;
background-color: rgba(0, 0, 0, 0.1);
border: 10px;
border-radius: 8px;
padding: 10px;
}}
QPushButton:hover {{
background-color: rgba(0, 0, 0, 0.5);
}}
QPushButton:pressed {{
background-color: none;
}}
""")
return button
def create_url_bar(self):
search = QLineEdit()
search.setStyleSheet("""QLineEdit {
min-width: 300px;
padding: 10px;
margin-left: 50px;
margin-right: 30px;
border-width: 10px;
border-radius: 8px;
background-color: rgba(0, 0, 0, 0.2);
color: white;
}
QLineEdit:hover {
background-color: #454549;
}
""")
return search
def init_layout(self):
self.setStyleSheet("""
background: #2A292E;
max-height: 40px;
""")
self.frame_layout.addWidget(self.back_btn, 0)
self.frame_layout.addWidget(self.forward_btn, 0)
self.frame_layout.addWidget(self.refresh_btn, 0)
self.frame_layout.addWidget(self.url_bar, 1)
self.setLayout(self.frame_layout)
def on_back(self):
if self.browser is not None:
self.browser.GoBack()
def on_forward(self):
if self.browser is not None:
self.browser.GoForward()
def on_refresh(self):
if self.browser is not None:
self.browser.Reload()
def on_search(self):
if self.browser is not None:
url = self.url_bar.text()
self.browser.LoadUrl(url)
if __name__ == "__main__":
app = QApplication([])
nav = NavigationBar()
nav.show()
app.exec()
问题是用于渲染浏览器的 QWindow
被隐藏了。解决方案是使用 QWidget::createWindowContainer()
创建一个 QWidget 并使用布局添加它。
import sys
from cefpython3 import cefpython as cef
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QWindow
from PyQt5.QtWidgets import QApplication, QFrame, QGridLayout, QMainWindow, QVBoxLayout, QWidget
from navbar import NavigationBar
class ChromiumApplication(QApplication):
def __init__(self):
super().__init__([])
self.timer = self.create_timer()
def create_timer(self):
timer = QTimer()
timer.timeout.connect(self.on_timeout)
timer.start(10)
return timer
def on_timeout(self):
cef.MessageLoopWork()
class ChromiumBrowserWindow(QMainWindow):
DEFAULT_TITLE = "Chromium Browser"
DEFAULT_WIDTH = 800
DEFAULT_HEIGHT = 600
def __init__(self):
super().__init__()
self.chrome = None
self.web_view = None
self.setWindowTitle(self.DEFAULT_TITLE)
self.init_window()
self.show()
def init_window(self):
self.resize(self.DEFAULT_WIDTH, self.DEFAULT_HEIGHT)
self.web_view = WebViewWidget()
self.chrome = NavigationBar(parent=self, browser=self.web_view.browser)
frame = QFrame()
self.setCentralWidget(frame)
layout = QGridLayout(frame)
layout.addWidget(self.chrome, 0, 0)
layout.setColumnStretch(0, 1)
layout.addWidget(self.web_view, 1, 0)
layout.setRowStretch(1, 2)
layout.setContentsMargins(0, 0, 0, 0)
def closeEvent(self, event):
if self.web_view.browser is not None:
self.web_view.browser.CloseBrowser(True)
del self.web_view.browser
class WebViewWidget(QWidget):
DEFAULT_URL = "https://www.google.com"
HANDLERS = []
def __init__(self, parent=None):
super().__init__(parent)
self._browser = None
self._browser_widget = None
lay = QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
self.init_browser()
@property
def browser(self):
return self._browser
@browser.deleter
def browser(self):
self._browser = None
def init_browser(self):
browser_window = QWindow()
window_config = cef.WindowInfo()
window_config.SetAsChild(
int(browser_window.winId()), list(self.rect().getRect())
)
self._browser = cef.CreateBrowserSync(window_config, url=self.DEFAULT_URL)
self._browser_widget = QWidget.createWindowContainer(browser_window)
self.layout().addWidget(self._browser_widget)
self.set_handlers()
def set_handlers(self):
for handler in self.HANDLERS:
self.browser.SetClientHanlder(handler(self))
def resizeEvent(self, event):
if self.browser and self._browser_widget:
self.browser.SetBounds(*self._browser_widget.geometry().getRect())
self.browser.NotifyMoveOrResizeStarted()
if __name__ == "__main__":
sys.excepthook = cef.ExceptHook
cef.Initialize()
app = ChromiumApplication()
window = ChromiumBrowserWindow()
app.exec()
app.timer.stop()
cef.Shutdown()