cef python3 блокировать UI на windows с tkinter - PullRequest
0 голосов
/ 13 июля 2020

Я делаю приложение с tkinter в python 3.7.8 .

Мне нужно показать карту, поэтому я использую Folium для его генерации и cef python3 для его отображения (поскольку он генерируется как html с javascript)

Он отлично работает на Linux, но когда Я пытаюсь протестировать его на Windows 10, карта отображается, я могу нажимать кнопки, но не могу взаимодействовать с любым tkinter.Entry, если я не щелкните другое окно , а затем вернитесь в программу окна.

Я предположил, что это проблема с фокусом, но даже пытался установить фокус cef python3 браузер на 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 и все остальное).

...