如何在cefpython中调整BrowserFrame大小以适配滚动操作
问题根源
你当前用Canvas实现的滚动本质是移动视口展示scrollable_frame的不同区域,滚动操作本身不会触发BrowserFrame的<Configure>事件,只有BrowserFrame自身尺寸变化时才会触发该事件重设CEF窗口大小,所以滚动时CEF窗口不会同步调整。
注意:原代码中browser_frame同时调用了grid和pack方法,同一控件只能使用一种布局管理器,建议删掉grid调用,保留pack即可,否则会触发布局冲突。
解决方案
需要在滚动事件触发时主动同步调整BrowserFrame及内部CEF窗口的尺寸,修改点如下:
1. 给BrowserFrame新增主动更新尺寸的方法
修改BrowserFrame类,把尺寸更新逻辑抽离为公共方法方便滚动时调用:
class BrowserFrame(tk.LabelFrame): def __init__(self, master=None, **kw): super().__init__(master, text='Browser', **kw) self.browser = None self.bind('<Configure>', self.on_configure) # 省略原有其他方法,新增以下方法 def update_browser_bounds(self, width=None, height=None): if not self.browser: return target_width = width if width else self.winfo_width() target_height = height if height else self.winfo_height() if WINDOWS: ctypes.windll.user32.SetWindowPos( self.browser.GetWindowHandle(), 0, 0, 0, target_width, target_height, 0x0002) elif LINUX: self.browser.SetBounds(0, 0, target_width, target_height)
2. 修改滚动逻辑,滚动时同步调整BrowserFrame尺寸
修改main函数里的鼠标滚轮回调,根据滚动方向动态调整BrowserFrame尺寸:
def on_mousewheel(event): shift = (event.state & 0x1) != 0 scroll = -1 if event.delta > 0 else 1 if shift: canvas.xview_scroll(scroll, "units") # 向右滚动时增加BrowserFrame宽度,50为增量系数可自定义 new_width = browser_frame.winfo_width() + (scroll * -50) browser_frame.config(width=new_width) browser_frame.update_browser_bounds(width=new_width) else: canvas.yview_scroll(scroll, "units") # 向下滚动时增加BrowserFrame高度,50为增量系数可自定义 new_height = browser_frame.winfo_height() + (scroll * -50) browser_frame.config(height=new_height) browser_frame.update_browser_bounds(height=new_height)
3. 修正CEF初始化的错误参数
原on_configure方法里初始化CEF的rect参数写死了150的左偏移,会导致CEF窗口初始位置错位,修改为:
def on_configure(self, event): global urlset urlset = "http://www.google.com" if self.browser is None: self.update() # 修正初始rect的偏移为0,尺寸和当前frame一致 rect = [0,0, self.winfo_width(), self.winfo_height()] cef_winfo = cef.WindowInfo() win_id = self.get_window_handle() cef_winfo.SetAsChild(win_id, rect) self.browser = cef.CreateBrowserSync(cef_winfo, url=urlset) self.cef_loop() # 原有窗口resize逻辑保留 if WINDOWS: ctypes.windll.user32.SetWindowPos( self.browser.GetWindowHandle(), 0, 0, 0, event.width, event.height, 0x0002) elif LINUX: self.browser.SetBounds(0, 0, event.width, event.height)
内容的提问来源于stack exchange,提问作者mrpy
相关产品推荐
相关产品推荐

