我尝试使用 wxPython 和 CEFPython 创建自己的浏览器。浏览器可以有多个选项卡,并且在每个选项卡中都应该打开 chromeWindow。部分代码如下。
def CreateMessageLoopTimer(timerMillis):
# This function gets called multiple times for each ChromeWindow
# instance.
global g_messageLoopTimer
Debug("CreateMesageLoopTimer")
if g_messageLoopTimer:
return
g_messageLoopTimer = wx.Timer()
g_messageLoopTimer.Start(timerMillis)
Debug("g_messageLoopTimer.GetId() = "\
+str(g_messageLoopTimer.GetId()))
""" !!!!!!!!!!!!!!!! THIS IS WHERE I GET THE ERROR !!!!!!!!!!!!!!!!
wx.EVT_TIMER(g_messageLoopTimer, g_messageLoopTimer.GetId(),\
MessageLoopTimer)
class ChromeWindow(wx.Window):
"""
Standalone CEF component. The class provides facilites for interacting
with wx message loop
"""
def __init__(self, parent, url="", useTimer=True,
timerMillis=DEFAULT_TIMER_MILLIS, browserSettings=None,
size=(-1, -1), *args, **kwargs):
wx.Window.__init__(self, parent, id=wx.ID_ANY, size=size,
*args, **kwargs)
# This timer is not used anymore, but creating it for backwards
# compatibility. In one of external projects ChromeWindow.timer.Stop()
# is being called during browser destruction.
self.timer = wx.Timer()
# On Linux absolute file urls need to start with "file://"
# otherwise a path of "/home/some" is converted to "http://home/some".
if platform.system() in ["Linux", "Darwin"]:
if url.startswith("/"):
url = "file://" + url
self.url = url
windowInfo = cefpython.WindowInfo()
if platform.system() == "Windows":
windowInfo.SetAsChild(self.GetHandle())
elif platform.system() == "Linux":
windowInfo.SetAsChild(self.GetGtkWidget())
elif platform.system() == "Darwin":
(width, height) = self.GetClientSizeTuple()
windowInfo.SetAsChild(self.GetHandle(),
[0, 0, width, height])
else:
raise Exception("Unsupported OS")
if not browserSettings:
browserSettings = {}
# Disable plugins:
# | browserSettings["plugins_disabled"] = True
cefpython.Initialize()
self.browser = cefpython.CreateBrowserSync(windowInfo,
browserSettings=browserSettings, navigateUrl=url)
if platform.system() == "Windows":
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.Bind(wx.EVT_SIZE, self.OnSize)
self._useTimer = useTimer
if useTimer:
CreateMessageLoopTimer(timerMillis)
else:
# Currently multiple EVT_IDLE events might be registered
# when creating multiple ChromeWindow instances. This will
# result in calling CEF message loop work multiple times
# simultaneously causing performance penalties and possibly
# some unwanted behavior (CEF Python Issue 129).
Debug("WARNING: Using EVT_IDLE for CEF message loop processing"\
" is not recommended")
self.Bind(wx.EVT_IDLE, self.OnIdle)
self.Bind(wx.EVT_CLOSE, self.OnClose)
class TabBrowser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, style = wx.WANTS_CHARS)
self.parent = parent
button_close1 = wx.Button(self, label="close1", size=(30, 30), pos=(0, -30))
self.Bind(wx.EVT_BUTTON, self.OnClose, button_close1)
# self._browser = html2.WebView.New(self)
# self._browser.LoadURL("https://www.google.com")
self._browser = ChromeWindow(self, url="https://www.google.com", useTimer=True)
self._navbar = NavBar(self, self._browser)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self._navbar, 0, wx.EXPAND)
sizer.Add(self._browser, 1, wx.EXPAND)
self.SetSizer(sizer)
ch = DefaultClientHandler(self)
self.SetClientHandler(ch)
if self.navigationBar:
self.UpdateButtonsState()
class WebFrame(wx.Frame):
def __init__(self, parent, title, pos, size):
super().__init__(parent, title = title, pos = pos, size = size)
self.setup_icon()
# Create a panel and notebook (tabs holder)
p = wx.Panel(self)
self.nb = fnb.FlatNotebook(p, agwStyle = fnb.FNB_SMART_TABS | fnb.FNB_NAV_BUTTONS_WHEN_NEEDED | fnb.FNB_COLOURFUL_TABS | fnb.FNB_X_ON_TAB)
self.nb.Bind(wx.EVT_KEY_DOWN, self.onKeyPress)
self.nb.SetWindowStyleFlag(wx.WANTS_CHARS)
# Create the tab windows
tab1 = TabBrowser(self.nb)
tab2 = TabBrowser(self.nb)
# Add the windows to tabs and name them.
self.nb.AddPage(tab1, "New Tab 1")
self.nb.AddPage(tab2, "New Tab 2")
# Set noteboook in a sizer to create the layout
sizer = wx.BoxSizer()
sizer.Add(self.nb, 1, wx.EXPAND)
p.SetSizer(sizer)
...
每个选项卡都应在代码中使用 cefpython.CreateBrowserSync()。运行代码后,出现以下错误。我不知道如何解决它。
D:\browser>python webbrowserApp.py
DevTools listening on ws://127.0.0.1:51216/devtools/browser/b1591854-6ec5-4e26-bcf0-1eee5da29700
webbrowserApp.py:38: wxPyDeprecationWarning: Call to deprecated item __call__. Use :meth:`EvtHandler.Bind` instead.
MessageLoopTimer)
Traceback (most recent call last):
File "webbrowserApp.py", line 332, in <module>
app = MyApp()
File "webbrowserApp.py", line 202, in __init__
self.InitBrowser()
File "webbrowserApp.py", line 205, in InitBrowser
webbrowser = WebFrame(None, "My Web App", pos = (100, 100), size = (WIDTH, HEIGHT))
File "webbrowserApp.py", line 252, in __init__
tab1 = TabBrowser(self.nb)
File "webbrowserApp.py", line 218, in __init__
self._browser = ChromeWindow(self, url="https://www.google.com", useTimer=True)
File "webbrowserApp.py", line 120, in __init__
CreateMessageLoopTimer(timerMillis)
File "webbrowserApp.py", line 38, in CreateMessageLoopTimer
MessageLoopTimer)
File "C:\Python37\lib\site-packages\wx\core.py", line 82, in deprecated_func
return item(*args)
File "C:\Python37\lib\site-packages\wx\core.py", line 1504, in __call__
assert len(args) == 2 + self.expectedIDs
AssertionError
如果有人知道这个问题,请帮助我。