如何使用 CEFPython 在 Tkinter 窗口中添加 WebBrowser 小部件?

问题描述 投票:0回答:1

我想在我的 tkinter 应用程序中显示一个 WebBrowser。根据下面的例子:

##############
#  label     #
#————————————#
# webbrowser #
##############

这是我尝试过的: https://github.com/iCarlosCode/Problematika/blob/88a0f13cbdc4ee48ac9690b3ae26cf231ce3c340/calculator/cef3.py

我尝试复制cefpython示例并使用BrowserFrame,但它不起作用。 cefpython tkinter 示例: https://github.com/cztomczak/cefpython/blob/master/examples/tkinter_.py

有人可以帮助我吗?

python tkinter chromium-embedded tkinter-layout cefpython
1个回答
3
投票

因此,您的主要代码有两个核心问题:

  1. 您没有初始化
    cefpython
  2. 您的
    browser_frame
    未配置为适合整个区域

简而言之,答案是:

import tkinter as tk
from tkinter import *
from cefpython3 import cefpython as cef
import ctypes

def main():
    win = Tk()
    cef.Initialize()

    win.minsize(600,600)
    win.grid_columnconfigure(0, weight=1)
    win.grid_rowconfigure(0, weight=1)

    #Create Frame
    frame = Frame(win, bg='black')
    frame.grid(row=0, column=0, sticky=('NSWE'))

    # Create Browser Frame
    browser_frame = BrowserFrame(frame)
    browser_frame.pack(fill=tk.BOTH, expand=tk.YES)

    win.mainloop()
    cef.Shutdown()

class BrowserFrame(tk.Frame):

    def __init__(self, mainframe, navigation_bar=None):
        self.navigation_bar = navigation_bar
        self.closing = False
        self.browser = None
        tk.Frame.__init__(self, mainframe)
        self.mainframe = mainframe
        self.bind("<FocusIn>", self.on_focus_in)
        self.bind("<FocusOut>", self.on_focus_out)
        self.bind("<Configure>", self.on_configure)
        """For focus problems see Issue #255 and Issue #535. """
        self.focus_set()

    #URLURLURL
    def embed_browser(self):
        window_info = cef.WindowInfo()
        rect = [0, 0, self.winfo_width(), self.winfo_height()]
        window_info.SetAsChild(self.get_window_handle(), rect)
        self.browser = cef.CreateBrowserSync(window_info,
                                             url="file:///calculo.html")
        assert self.browser
        #self.browser.SetClientHandler(LifespanHandler(self))
        #self.browser.SetClientHandler(LoadHandler(self))
        #self.browser.SetClientHandler(FocusHandler(self))
        self.message_loop_work()

    def get_window_handle(self):
        if self.winfo_id() > 0:
            return self.winfo_id()
        else:
            raise Exception("Couldn't obtain window handle")

    def message_loop_work(self):
        cef.MessageLoopWork()
        self.after(10, self.message_loop_work)

    def on_configure(self, _):
        if not self.browser:
            self.embed_browser()

    def on_root_configure(self):
        # Root <Configure> event will be called when top window is moved
        if self.browser:
            self.browser.NotifyMoveOrResizeStarted()

    def on_mainframe_configure(self, width, height):
        if self.browser:
            if WINDOWS:
                ctypes.windll.user32.SetWindowPos(
                    self.browser.GetWindowHandle(), 0,
                    0, 0, width, height, 0x0002)
            self.browser.NotifyMoveOrResizeStarted()

    def on_focus_in(self, _):
        #logger.debug("BrowserFrame.on_focus_in")
        if self.browser:
            self.browser.SetFocus(True)

    def on_focus_out(self, _):
        #logger.debug("BrowserFrame.on_focus_out")
        """For focus problems see Issue #255 and Issue #535. """
        pass

    def on_root_close(self):
        #logger.info("BrowserFrame.on_root_close")
        if self.browser:
            #logger.debug("CloseBrowser")
            self.browser.CloseBrowser(True)
            self.clear_browser_references()
        else:
            #logger.debug("tk.Frame.destroy")
            self.destroy()
            

    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.browser = None

class LifespanHandler(object):

    def __init__(self, tkFrame):
        self.tkFrame = tkFrame

    def OnBeforeClose(self, browser, **_):
        #logger.debug("LifespanHandler.OnBeforeClose")
        self.tkFrame.quit()

class LoadHandler(object):

    def __init__(self, browser_frame):
        self.browser_frame = browser_frame

    def OnLoadStart(self, browser, **_):
        if self.browser_frame.master.navigation_bar:
            self.browser_frame.master.navigation_bar.set_url(browser.GetUrl())


class FocusHandler(object):
    """For focus problems see Issue #255 and Issue #535. """

    def __init__(self, browser_frame):
        self.browser_frame = browser_frame

    def OnTakeFocus(self, next_component, **_):
        pass#logger.debug("FocusHandler.OnTakeFocus, next={next}".format(next=next_component))

    def OnSetFocus(self, source, **_):
            return True

    def OnGotFocus(self, **_):
        #logger.debug("FocusHandler.OnGotFocus")
        pass


if __name__ == '__main__':
    main()

因此,要解决问题 1,在 tkinter 主循环中,您必须输入

cef.Initialize()
,然后输入
cef.Shutdown()
将其关闭。问题是我们仍然看不到框架,因为您没有执行
grid_columnconfigure
也没有执行
grid_rowconfigure
,所以即使您执行了
sticky='nsew'
,它也没有执行任何操作,因为行和列没有添加权重,为了纠正这个问题,我使用了 pack 代替。

在为我创建的 Windows 上:

令人烦恼的是,这在

cefpython
上效果不佳,因为 MathJax 未加载,要纠正此问题,您需要将
calculo.html
更改为:

<!DOCTYPE html>
<html>
<head>
<title>MathJax TeX Test Page</title>
<script type="text/x-mathjax-config" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
  MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
</script>
<script type="text/javascript" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
</head>
<body>
When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ \[\\ yep \\x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]
</body>
</html>

因为

text/x-mathjax-config
不支持内联类型
cefpython

这会创建:

就像一个快速指针一样,在 mathjax 加载之前需要几秒钟的时间,因此托管一个 本地 MathJax 配置可能是一个想法,因为这很可能会加快加载时间。

相对于在此之上有一个标签,通过简单地将变量框架移动到

grid(row=1, column=0...
(并更改行权重),然后在
grid(row=0, column=0...
中添加标签,编码起来会相当简单。

© www.soinside.com 2019 - 2024. All rights reserved.