文章目录
前言
这段时间研究了cefpython3,发现了一个问题,就是说点击链接时会弹出一个子窗口。看到网上没有相应的教程,就发出来了
思路
在C++的版本看到,有一个函数OnBeforePopup可以搞定,但cefpython并不一样,于是查阅官方文档和PYPI在github的帮助文档里Quick links的API Index中找到:
解释
interface是接口,要用browser.SetClientHandler设置,传入对象,cef会在相应事件发生时调用(可多次使用)。
#例子(代码段)
class LoadHandler():#类名不一定是这个
def OnBeforePopup(self,target_url,**_):#只需要target_url参数,其他关键字参数不要
print(target_url)#一些处理
return True#返回True值就不弹出
window_info = cef.WindowInfo()
browser = cef.CreateBrowserSync(window_info,url=url)
browser.SetClientHandler(LoadHandler())#传入对象,注意是对象不是类
#TODO:剩余代码
一个tkinter的绑定
直接运行得到一个简易浏览器,导入得到Browser类,当tkinter.Frame使用
可传入参数url
只要覆盖NewWindow方法,接受位置参数url并返回小写的"break"
即可
默认已经是在原frame中打开,而test中是用ttk.notebook新标签页打开
from cefpython3 import cefpython as cef
import tkinter as tk
import platform
WINDOWS = (platform.system() == "Windows")
LINUX = (platform.system() == "Linux")
MAC = (platform.system() == "Darwin")
# Fix for PyCharm hints warnings
WindowUtils = cef.WindowUtils()
cef.Initialize() #init
class Browser(tk.Frame):
class LoadHandler(object):
def __init__(self, browser):
self.browser = browser
def OnBeforePopup(self,target_url,**a):
res = self.browser.NewWindow(target_url)
if res == "break":
return True
class FocusHandler(object):
"From cefpython3.example.tkinter_"
def __init__(self, browser_frame):
self.browser_frame = browser_frame
def OnSetFocus(self, source, **_):
return False
def OnGotFocus(self, **_):
"""Fix CEF focus issues (#255). Call browser frame's focus_set
to get rid of type cursor in url entry widget."""
self.browser_frame.focus_set()
def __init__(self,*a,url="",**b):
super().__init__(*a,**b)
#create browser
window_info = cef.WindowInfo()
rect = [0, 0, self.winfo_width(), self.winfo_height()]
window_info.SetAsChild(self.get_window_handle(), rect)
if not url:
url="https://www.baidu.com/"
self.browser = cef.CreateBrowserSync(window_info,url=url)
assert self.browser
self.browser.SetClientHandler(self.LoadHandler(self))
self.browser.SetClientHandler(self.FocusHandler(self))
#fit frame
self.bind("<Configure>", self._configure)
def _configure(self, event):
res=self.event_generate("<<Configure>>")
if res=="break":
return
width = event.width
height = event.height
if WINDOWS:
WindowUtils.OnSize(self.winfo_id(), 0, 0, 0)
elif LINUX:
self.browser.SetBounds(0, 0, width, height)
self.browser.NotifyMoveOrResizeStarted()
def NewWindow(self,url):
self.load(url)
return "break"
def loadurl(self,url):
self.browser.StopLoad()
self.browser.LoadUrl(url)
def geturl(self):
return self.browser.GetUrl()
def reload(self):
self.browser.Reload()
def get_window_handle(self):
"From cef"
if self.winfo_id() > 0:
return self.winfo_id()
elif MAC:
# On Mac window id is an invalid negative value (Issue #308).
# This is kind of a dirty hack to get window handle using
# PyObjC package. If you change structure of windows then you
# need to do modifications here as well.
# noinspection PyUnresolvedReferences
from AppKit import NSApp
# noinspection PyUnresolvedReferences
import objc
# Sometimes there is more than one window, when application
# didn't close cleanly last time Python displays an NSAlert
# window asking whether to Reopen that window.
# noinspection PyUnresolvedReferences
return objc.pyobjc_id(NSApp.windows()[-1].contentView())
else:
raise Exception("Couldn't obtain window handle")
def maincefloop(n=200):
cef.MessageLoopWork()
tk._default_root.after(n, maincefloop,n)
def bye():
cef.Shutdown()
def test():
def makenew(url):
b = Browser(note,url=url)
note.add(b,text=url.replace("https://","").replace("http://","").replace("blob://","")[:25])
note.select(note.index("end")-1)
b.NewWindow=lambda url:makenew(url) or "break"
from tkinter import ttk
root = tk.Tk()
note = ttk.Notebook()
note.pack(expand=1,fill="both")
makenew("https://www.baidu.com")
root.title("cefweb.Browser")
root.geometry("800x600")
maincefloop()
root.mainloop()
bye()
if __name__ == "__main__":
test()
注释懒得写了,都是cef官方example给的,文档也很详细,就不多写了
总结
文档会看吗?
不要吝啬你的赞!