python:tkinter + cef 模仿 mdict 界面

cefpython3 其上游是C++开发的CEF(基于webkit、V8),
CEF 即 (Chromium Embedder Framework),
是基于Google Chromium项目的开源 Web browser控件(WebView)。

可查看github文档:cefpython api

pip install cefpython3
cefpython3-66.1-py2.py3-none-win_amd64.whl (69.0 MB)
Successfully installed cefpython3-66.1

cd \Python37\Lib\site-packages\cefpython3\examples
copy tkinter_.py  tk_cef.py
用的图片在 \Python37\Lib\site-packages\cefpython3\examples\resources\
编写 tk_cef.py 如下

# -*- coding: utf-8 -*-
# Example of embedding CEF Python browser using Tkinter toolkit.
# This example has two widgets: a navigation bar and a browser.
#
# Tested configurations:
# - Tk 8.5 on Windows/Mac
# - Tk 8.6 on Linux
# - CEF Python v55.3+
#
import ctypes
try:import tkinter as tk
except ImportError:import Tkinter as tk
import sys
import os
import platform
import logging as _logging
from cefpython3 import cefpython as cef
# help(cef.PyBrowser)
# Fix for PyCharm hints warnings
WindowUtils = cef.WindowUtils()# Platforms
WINDOWS = (platform.system() == "Windows")
LINUX = (platform.system() == "Linux")
MAC = (platform.system() == "Darwin")# Globals
logger = _logging.getLogger("tk_cef.py")
baseurl = "http://localhost:8888/"# Constants
# Tk 8.5 doesn't support png images
IMAGE_EXT = ".png" if tk.TkVersion > 8.5 else ".gif"def main():logger.setLevel(_logging.DEBUG)stream_handler = _logging.StreamHandler()formatter = _logging.Formatter("[%(filename)s] %(message)s")stream_handler.setFormatter(formatter)logger.addHandler(stream_handler)logger.info("CEF Python {ver}".format(ver=cef.__version__))logger.info("Python {ver} {arch}".format(ver=platform.python_version(), arch=platform.architecture()[0]))logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel')))assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this"# 替换python预定义异常处理逻辑,为保证异常发生时能够结束所有进程sys.excepthook = cef.ExceptHook  # To shutdown all CEF processes on error# Tk must be initialized before CEF otherwise fatal error (Issue #306)root = tk.Tk()app = MainFrame(root)settings = {}if MAC:settings["external_message_pump"] = Truecef.Initialize(settings=settings)app.mainloop()logger.debug("Main loop exited")cef.Shutdown() # 结束进程class MainFrame(tk.Frame):""" tk GUI 主界面 """def __init__(self, root):self.browser_frame = Noneself.navigation_bar = Noneself.root = root# Rootroot.geometry("900x640")tk.Grid.rowconfigure(root, 0, weight=1)tk.Grid.columnconfigure(root, 0, weight=1)# MainFrametk.Frame.__init__(self, root)self.master.title("tkinter + cef")self.master.protocol("WM_DELETE_WINDOW", self.on_close)self.master.bind("<Configure>", self.on_root_configure)self.setup_icon()self.bind("<Configure>", self.on_configure)self.bind("<FocusIn>", self.on_focus_in)self.bind("<FocusOut>", self.on_focus_out)# NavigationBarself.navigation_bar = NavigationBar(self)self.navigation_bar.grid(row=0, column=0,sticky=(tk.N + tk.S + tk.E + tk.W))tk.Grid.rowconfigure(self, 0, weight=0)tk.Grid.columnconfigure(self, 0, weight=0)# BrowserFrameself.browser_frame = BrowserFrame(self, self.navigation_bar)self.browser_frame.grid(row=1, column=0,sticky=(tk.N + tk.S + tk.E + tk.W))tk.Grid.rowconfigure(self, 1, weight=1)tk.Grid.columnconfigure(self, 0, weight=1)# Pack MainFrameself.pack(fill=tk.BOTH, expand=tk.YES)def on_root_configure(self, _):#logger.debug("MainFrame.on_root_configure")if self.browser_frame:self.browser_frame.on_root_configure()def on_configure(self, event):logger.debug("MainFrame.on_configure")if self.browser_frame:width = event.widthheight = event.heightif self.navigation_bar:height = height - self.navigation_bar.winfo_height()self.browser_frame.on_mainframe_configure(width, height)def on_focus_in(self, _):logger.debug("MainFrame.on_focus_in")def on_focus_out(self, _):logger.debug("MainFrame.on_focus_out")def on_close(self):if self.browser_frame:self.browser_frame.on_root_close()self.browser_frame = Noneelse:self.master.destroy()def get_browser(self):if self.browser_frame:return self.browser_frame.browserreturn Nonedef get_browser_frame(self):if self.browser_frame:return self.browser_framereturn Nonedef setup_icon(self):resources = os.path.join(os.path.dirname(__file__), "resources")icon_path = os.path.join(resources, "tkinter"+IMAGE_EXT)if os.path.exists(icon_path):self.icon = tk.PhotoImage(file=icon_path)# noinspection PyProtectedMemberself.master.call("wm", "iconphoto", self.master._w, self.icon)class BrowserFrame(tk.Frame):def __init__(self, mainframe, navigation_bar=None):self.navigation_bar = navigation_barself.closing = Falseself.browser = Nonetk.Frame.__init__(self, mainframe)self.mainframe = mainframeself.bind("<FocusIn>", self.on_focus_in)self.bind("<FocusOut>", self.on_focus_out)self.bind("<Configure>", self.on_configure)"""For focus problems see Issue #255 and Issue #535. """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)global baseurl # 创建浏览器self.browser = cef.CreateBrowserSync(window_info, url=baseurl)assert self.browserself.browser.SetClientHandler(LifespanHandler(self))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()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 movedif 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, _):logger.debug("BrowserFrame.on_focus_in")if self.browser:self.browser.SetFocus(True)def on_focus_out(self, _):logger.debug("BrowserFrame.on_focus_out")"""For focus problems see Issue #255 and Issue #535. """if LINUX and self.browser:self.browser.SetFocus(False)def on_root_close(self):logger.info("BrowserFrame.on_root_close")if self.browser:logger.debug("CloseBrowser")self.browser.CloseBrowser(True)self.clear_browser_references()else:logger.debug("tk.Frame.destroy")self.destroy()def clear_browser_references(self):# Clear browser references that you keep anywhere in your# code. All references must be cleared for CEF to shutdown cleanly.self.browser = Noneclass LifespanHandler(object):def __init__(self, tkFrame):self.tkFrame = tkFramedef OnBeforeClose(self, browser, **_):logger.debug("LifespanHandler.OnBeforeClose")self.tkFrame.quit()class LoadHandler(object):def __init__(self, browser_frame):self.browser_frame = browser_framedef OnLoadStart(self, browser, **_):pass#if self.browser_frame.master.navigation_bar:#   self.browser_frame.master.navigation_bar.set_url(browser.GetUrl())class FocusHandler(object):"""For focus problems see Issue #255 and Issue #535. """def __init__(self, browser_frame):self.browser_frame = browser_framedef OnTakeFocus(self, next_component, **_):logger.debug("FocusHandler.OnTakeFocus, next={next}".format(next=next_component))def OnSetFocus(self, source, **_):logger.debug("FocusHandler.OnSetFocus, source={source}".format(source=source))if LINUX:return Falseelse:return Truedef OnGotFocus(self, **_):logger.debug("FocusHandler.OnGotFocus")if LINUX:self.browser_frame.focus_set()class NavigationBar(tk.Frame):def __init__(self, master):self.back_state = tk.NONEself.forward_state = tk.NONEself.back_image = Noneself.forward_image = Noneself.reload_image = Nonetk.Frame.__init__(self, master)resources = os.path.join(os.path.dirname(__file__), "resources")# Back buttonback_png = os.path.join(resources, "back"+IMAGE_EXT)if os.path.exists(back_png):self.back_image = tk.PhotoImage(file=back_png)self.back_button = tk.Button(self, image=self.back_image,command=self.go_back)self.back_button.grid(row=0, column=0, padx=5, pady=2)# Forward buttonforward_png = os.path.join(resources, "forward"+IMAGE_EXT)if os.path.exists(forward_png):self.forward_image = tk.PhotoImage(file=forward_png)self.forward_button = tk.Button(self, image=self.forward_image,command=self.go_forward)self.forward_button.grid(row=0, column=1, padx=5, pady=2)# Reload buttonreload_png = os.path.join(resources, "reload"+IMAGE_EXT)if os.path.exists(reload_png):self.reload_image = tk.PhotoImage(file=reload_png)self.reload_button = tk.Button(self, image=self.reload_image,command=self.reload)self.reload_button.grid(row=0, column=2, padx=5, pady=2)# Url entryself.url_entry = tk.Entry(self)self.url_entry.bind("<FocusIn>", self.on_url_focus_in)self.url_entry.bind("<FocusOut>", self.on_url_focus_out)self.url_entry.bind("<Return>", self.on_load_url)self.url_entry.bind("<Button-1>", self.on_button1)self.url_entry.grid(row=0, column=3,sticky=(tk.N + tk.S + tk.E + tk.W))tk.Grid.rowconfigure(self, 0, weight=100)tk.Grid.columnconfigure(self, 3, weight=100)# go buttonself.go_button = tk.Button(self, text="go", command=self.go)self.go_button.grid(row=0, column=4, padx=5, pady=2)# prefix button 前缀匹配self.button2 = tk.Button(self, text="prefix", command=self.prefix)self.button2.grid(row=0, column=5, padx=5, pady=2)# Update state of buttonsself.update_state()def go(self):global baseurlurl = self.url_entry.get()if url.strip() =='':returnelif url.startswith("http://"):passelse:url = baseurl + "trans?txt=" + url.strip();if self.master.get_browser():self.master.get_browser().StopLoad()self.master.get_browser().LoadUrl(url)def prefix(self):global baseurlurl = self.url_entry.get()if url.strip() =='':returnelif url.startswith("http://"):if self.master.get_browser():self.master.get_browser().StopLoad()self.master.get_browser().LoadUrl(url)else:url = baseurl + "prefix?txt=" + url.strip();if self.master.get_browser():self.master.get_browser().StopLoad()self.master.get_browser().LoadUrl(url)def go_back(self):if self.master.get_browser():self.master.get_browser().GoBack()def go_forward(self):if self.master.get_browser():self.master.get_browser().GoForward()def reload(self):if self.master.get_browser():self.master.get_browser().Reload()def set_url(self, url):self.url_entry.delete(0, tk.END)self.url_entry.insert(0, url)def on_url_focus_in(self, _):logger.debug("NavigationBar.on_url_focus_in")def on_url_focus_out(self, _):logger.debug("NavigationBar.on_url_focus_out")def on_load_url(self, _):if self.master.get_browser():self.master.get_browser().StopLoad()self.master.get_browser().LoadUrl(self.url_entry.get())def on_button1(self, _):"""For focus problems see Issue #255 and Issue #535. """logger.debug("NavigationBar.on_button1")self.master.master.focus_force()def update_state(self):browser = self.master.get_browser()if not browser:if self.back_state != tk.DISABLED:self.back_button.config(state=tk.DISABLED)self.back_state = tk.DISABLEDif self.forward_state != tk.DISABLED:self.forward_button.config(state=tk.DISABLED)self.forward_state = tk.DISABLEDself.after(100, self.update_state)returnif browser.CanGoBack():if self.back_state != tk.NORMAL:self.back_button.config(state=tk.NORMAL)self.back_state = tk.NORMALelse:if self.back_state != tk.DISABLED:self.back_button.config(state=tk.DISABLED)self.back_state = tk.DISABLEDif browser.CanGoForward():if self.forward_state != tk.NORMAL:self.forward_button.config(state=tk.NORMAL)self.forward_state = tk.NORMALelse:if self.forward_state != tk.DISABLED:self.forward_button.config(state=tk.DISABLED)self.forward_state = tk.DISABLEDself.after(100, self.update_state)if __name__ == '__main__':main()

这个程序解决了 tkinter 嵌入 cef 后鼠标焦点失控的问题。

cefpython 入门教程 参考: Python GUI: cefpython3的简单分析和应用

web 服务程序:python:mdict + bottle = web 查询英汉词典

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/97219.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

车载APP软件外包开发流程

车载APP的开发流程涉及多个阶段&#xff0c;从概念到发布都需要仔细的规划和执行。以下是一个一般性的车载APP开发流程概述&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.需求分析和规划&#xff…

vulnhub靶机DarkHole_2

靶机下载地址&#xff1a;DarkHole: 2 ~ VulnHub 靶机发现 arp-scan -l 扫描端口 nmap --min-rate 10000 -p- 192.168.21.145 扫描服务 nmap -sV -sT -O -p22,80 192.168.21.145 漏洞扫描 nmap --scriptvuln -p22,80 192.168.21.145 这里有git源码泄露 git clone mirrors…

x.view(a,b)及x = x.view(x.size(0), -1) 的理解说明

x.view()就是对tensor进行reshape&#xff1a; 我们在创建一个网络的时候&#xff0c;会在Foward函数内看到view的使用。 首先这里是一个简单的网络&#xff0c;有卷积和全连接组成。它的foward函数如下&#xff1a; class NET(nn.Module):def __init__(self,batch_size):sup…

1.flink快速入门

前言 下图表示的是一个简单的flink-job的计算图&#xff0c;这种图被称为DAG(有向无环图)&#xff0c;表示的这个任务的计算逻辑&#xff0c;无论是spark、hive、还是flink都会把用户的计算逻辑转换为这样的DAG&#xff0c;数据的计算按照DAG触发&#xff0c;理论上只要构建出…

Seaborn数据可视化(一)

目录 1.seaborn简介 2.Seaborn绘图风格设置 21.参数说明&#xff1a; 2.2 示例&#xff1a; 1.seaborn简介 Seaborn是一个用于数据可视化的Python库&#xff0c;它是建立在Matplotlib之上的高级绘图库。Seaborn的目标是使绘图任务变得简单&#xff0c;同时产生美观且具有信…

【脚本推荐】网页字体渲染插件

下图是三种网页字体增强的效果对比。 **SUM&#xff1a;**前面两个都是通过脚本运行&#xff0c;而最后一个是通过扩展插件&#xff1b;中间的脚本&#xff08;字体渲染&#xff09;效果是最好的&#xff0c;可惜输入框没有效果&#xff0c;也就意味着如果现在网页上写写学习笔…

2023最新版本~KEIL5使用C++开发STM32

先看效果 开始教学 因为是第一次写这个配置教程 我会尽量详细些 打开一个Keil工程 移除本地core 添加在线core 第一次编译代码 不会有报错 修改main.c文件类型为C 点击魔术棒 把ARM编译器修改为V6 第二次编译会报错语法不兼容 我把汇编部分的这些代码做了…

Mac 使用 rar 命令行工具解压和压缩文件

在 Mac 中常遇到的压缩文件有 zip 和 rar 格式的&#xff0c;如果是 zip 格式的 Mac 系统默认双击一下文件就能直接解压了&#xff0c;但 rar 文件就不行。 需要额外下载 rar 工具了实现。 第一步&#xff1a;下载 rar 工具 工具网址&#xff1a;https://www.rarlab.com/dow…

安防监控视频云存储平台EasyNVR通道频繁离线的原因排查与解决

安防视频监控汇聚EasyNVR视频集中存储平台&#xff0c;是基于RTSP/Onvif协议的安防视频平台&#xff0c;可支持将接入的视频流进行全平台、全终端分发&#xff0c;分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。为了满足用户的集成与二次开发需求&#xf…

记录一次arcgis engine开发版本引入问题

之前基于arcigs 10.1vs2013开发的程序&#xff0c;现在拿出来要改&#xff0c;但是目前版本是arcgis10.7vs2017/vs2019,打开后无论如何替换引用版本&#xff0c;都报错 &#xff08;具体版本对应可以看这&#xff1a;ArcGIS Engine 与 Visual Studio 版本对照表_vs2019对应啥版…

神经网络基础-神经网络补充概念-02-逻辑回归

概念 逻辑回归是一种用于二分分类问题的统计学习方法&#xff0c;尽管名字中带有"回归"一词&#xff0c;但实际上它用于分类任务。逻辑回归的目标是根据输入特征来预测数据点属于某个类别的概率&#xff0c;然后将概率映射到一个离散的类别标签。 逻辑回归模型的核…

Git命令详解

1 常用命令 1&#xff09;初始化本地仓库 git init <directory> 是可选的&#xff0c;如果不指定&#xff0c;将使用当前目录。 2&#xff09;克隆一个远程仓库 git clone <url> 3&#xff09;添加文件到暂存区 git add <file> 要添加当前目录中的所…

Spring Boot 统一功能处理

目录 1.用户登录权限效验 1.1 Spring AOP 用户统一登录验证的问题 1.2 Spring 拦截器 1.2.1 自定义拦截器 1.2.2 将自定义拦截器加入到系统配置 1.3 拦截器实现原理 1.3.1 实现原理源码分析 2. 统一异常处理 2.1 创建一个异常处理类 2.2 创建异常检测的类和处理业务方法 3. 统一…

VALN-hybrid模式

实验拓扑及要求 一、实验思路 1.R1-R3按要求配置&#xff0c;R2不划分vlan使其全部都可以访问 2.交换机和路由器的交换机直连接口设为hybrid模式且R4-R6不带vlan标签访问路由器 3.交换机和交换机的两个直连接口设为hybrid模式且只允许R4-R6所在vlan标签通过 4.R4-R6只允许其…

音视频 FFmpeg音视频处理流程

ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x720 test_1280x720.flv推荐一个零声学院项目课&#xff0c;个人觉得老师讲得不错&#xff0c;分享给大家&#xff1a; 零声白金学习卡&#xff08;含基础架构/高性能存储/golang云原生/音视频/Linux内核&am…

C++进阶 特殊类的设计

本篇博客介绍&#xff1a;介绍几种特殊的类 特殊类的设计 设计一个类不能被拷贝设计一个类 只能在堆上创建对象设计一个类 只能在栈上创造对象设计一个类不能被继承单例模式饿汉模式懒汉模式单例模式对象的释放问题 总结 设计一个类不能被拷贝 我们的拷贝只会发生在两个场景当…

OSPF在广播类型的网络拓扑中DR和BDR的选举

指定路由器&#xff08;DR&#xff09;&#xff1a; 一个网段上的其他路由器都和指定路由器&#xff08;DR&#xff09;构成邻接关系&#xff0c;而不是它们互相之间构成邻接关系。 备份指定路由器&#xff08;BDR&#xff09;&#xff1a; 当DR出现问题&#xff0c;由BDR接…

prompt-engineering-note(面向开发者的ChatGPT提问工程学习笔记)

介绍&#xff1a; ChatGPT Prompt Engineering Learning Notesfor Developers (面向开发者的ChatGPT提问工程学习笔记) 课程简单介绍了语言模型的工作原理&#xff0c;提供了最佳的提示工程实践&#xff0c;并展示了如何将语言模型 API 应用于各种任务的应用程序中。 此外&am…

WebRTC | SDP详解

目录 一、SDP标准规范 1. SDP结构 2. SDP内容及type类型 二、WebRTC中的SDP结构 1. 媒体信息描述 &#xff08;1&#xff09;SDP中媒体信息格式 i. “artpmap”属性 ii. “afmtp”属性 &#xff08;2&#xff09;SSRC与CNAME &#xff08;3&#xff09;举个例子 &…