我正在 python 3.7.8 中使用tkinter制作应用程序。
我必须显示一张地图,所以我使用Folium生成它并使用cefpython3显示它(因为它使用 javascript 生成为 html)
它在 Linux 上运行良好,但是当我尝试在 Windows 10 上对其进行测试时,显示地图,我可以单击按钮,但除非我单击另一个窗口,否则无法与任何按钮交互,然后返回窗口程序。tkinter.Entry
我认为这是一个焦点问题,但即使尝试将 cefpython3 浏览器的焦点设置为 False,问题仍然存在。
这是 MapVisualizer 代码
class MapVisualizer(tk.Frame):
""" Generates the map with folium and then attach cefpython3 browser to the frame """
def __init__(self, root, size, mapPoints, zoom, pointDatas=None, **kargs):
self.browser_frame = None
self.navigation_bar = None
self.replaceFolium()
m = folium.Map(location=mapPoints, zoom_start=zoom, height=size[0], width=size[1], min_zoom=3, max_zoom=12)
for data_point in pointDatas:
folium.Marker(data_point[0], popup=data_point[1]).add_to(m)
m.save(resource_path("data/map_location.html"))
# Root
tk.Grid.rowconfigure(root, 0, weight=1)
tk.Grid.columnconfigure(root, 0, weight=1)
# MainFrame
tk.Frame.__init__(self, root)
# BrowserFrame
tk.Grid.rowconfigure(self, 1, weight=1)
tk.Grid.columnconfigure(self, 0, weight=1)
# Pack MainFrame
self.browser_frame = BrowserFrame(self, self.navigation_bar)
self.browser_frame.grid(row=1, column=0,
sticky=(tk.N + tk.S + tk.E + tk.W))
def on_root_configure(self, _):
if self.browser_frame:
self.browser_frame.on_root_configure()
def on_configure(self, event):
if self.browser_frame:
width = event.width
height = event.height
if self.navigation_bar:
height = height - self.navigation_bar.winfo_height()
self.browser_frame.on_mainframe_configure(width, height)
def on_focus_in(self, _):
self.browser.SetFocus(False)
def on_focus_out(self, _):
self.browser.SetFocus(False)
def on_close(self):
if self.browser_frame:
self.browser_frame.on_root_close()
self.master.destroy()
def get_browser(self):
if self.browser_frame:
return self.browser_frame.browser
return None
def get_browser_frame(self):
if self.browser_frame:
return self.browser_frame
return None
def onClose(self):
cef.Shutdown()
这是浏览器代码
class BrowserFrame(tk.Frame):
def __init__(self, master, navigation_bar=None):
self.navigation_bar = navigation_bar
cef.Initialize()
self.closing = False
self.browser = None
tk.Frame.__init__(self, master)
self.bind("<FocusIn>", self.on_focus_in)
self.bind("<FocusOut>", self.on_focus_out)
self.bind("<Configure>", self.on_configure)
self.focus_set()
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=f"file:///{os.getcwd()}/data/map_location.html") #todo
assert self.browser
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()
elif MAC:
from AppKit import NSApp
import objc
return objc.pyobjc_id(NSApp.windows()[-1].contentView())
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)
elif LINUX:
self.browser.SetBounds(0, 0, width, height)
self.browser.NotifyMoveOrResizeStarted()
def on_focus_in(self, _):
if self.browser:
self.browser.SetFocus(True)
def on_focus_out(self, _):
if self.browser:
self.browser.SetFocus(False)
def on_root_close(self):
if self.browser:
self.browser.CloseBrowser(True)
self.clear_browser_references()
self.destroy()
def clear_browser_references(self):
self.browser = None
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):
def __init__(self, browser_frame):
self.browser_frame = browser_frame
def OnTakeFocus(self, next_component, **_):
self.browser_frame.browser.SetFocus(False)
def OnSetFocus(self, source, **_):
self.browser_frame.browser.SetFocus(False)
return False
def OnGotFocus(self, **_):
self.browser_frame.browser.SetFocus(False)
没有错误或调试消息,正如我所说,这个问题只发生在 Windows 上(相同的env目录和所有内容)。