python:tkinterweb 简单又好用的 htmlview 组件

2023-10-27

tkinterweb  是简单又好用的 webview 组件,也可用来显示本地 html文件。

pip install tkinterweb ;

pip install readmdict ; 参见: 使用Python调用mdx字典文件进行查词

安装 MDict 去 MDict | One app for all dictionaries 下载

测试 html view 程序 tk_read_mdict.py 如下:

# -*- coding: utf-8 -*-
""" 查询英汉词典 """
import os
import time
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinterweb import HtmlFrame
import pygame
from readmdict import MDX  # pip install readmdict
import win32com.client  # TTS
sapi = win32com.client.Dispatch("SAPI.SpVoice")

#pygame.init()
pygame.mixer.init()

os.chdir("/MDictPC/doc")

def speak():
    """ TTS发音 """
    txt = frame.get_currently_selected_text()
    if txt == None:
        txt = entry.get()
    if txt.strip() !='':
        sapi.Speak(txt)

def mplay(filename):
    """播放.mp3 """
    if pygame.mixer.music.get_busy():
        print("mixer.music.get_busy")
        return 1
    if not os.path.exists(filename):
        print(f"{filename} not found.")
        return 2
    fn,ext = os.path.splitext(filename)
    if ext.lower() == '.mp3':
        pygame.mixer.music.load(filename)
        pygame.mixer.music.play()
    else:
        print(f"{filename} is not .mp3")
        return 3
    return 0


def open_mdx():
    """ 读.mdx词典文件 """
    file1 = ''
    filetypes = [('mdx file','.mdx')]
    file1 = filedialog.askopenfilename(initialdir=".", filetypes=filetypes)
    if file1 == '': return
    start_time = time.time()
    path1 = os.path.dirname(file1)
    os.chdir(path1)
    global headwords, items
    # 加载.mdx文件
    fname = os.path.basename(file1)
    mdx = MDX(fname)
    headwords = [*mdx]       # 单词名列表
    items = [*mdx.items()]   # 释义html源码列表
    n = len(headwords)
    m = len(items)
    end_time = time.time()
    print('cost %f second' % (end_time - start_time))
    if n == m:
        var1.set(f'{fname} 加载成功:共{n}条')
    else:
        var1.set(f'ERROR:{fname} 加载失败 {n}!={m}')
        return

def query(self):
    """  输入英文单词,并查询 """
    if not entry.get():
        messagebox.showinfo("请先选择词典","输入单词不能为空")
        return
    txt = entry.get()
    if txt.startswith("http://") or txt.startswith("https://"):
        frame.load_url(txt)
        frame.on_link_click(sound)
    else:
        prefix(txt)
        query1(txt)

def query1(txt):
    """  查询英文单词 """
    global var1, headwords
    try:
        type(headwords)
    except NameError:
        messagebox.showinfo("提示", "请先选择词典!")
        return
    word = txt.lower().encode()
    word1 = txt.capitalize().encode() # 第1个字母变大写
    try: # 查词,返回单词和html文件
        if word in headwords:
            wordIndex = headwords.index(word)
        else:
            wordIndex = headwords.index(word1)
        word,html = items[wordIndex]
        result = html.decode()
        if result.startswith('@@@LINK='):
            w = result[8:].strip()
            result = '<a href="entry://' +w+ '">' +w+ '</a>'
        else:
            result = result.replace('<img src="','<img src="./data/')
            result = result.replace('"/thumb/','"data/thumb/')
        frame.enable_stylesheets(enabled=True)
        frame.enable_images(enabled=True)
        frame.load_html(result)
        frame.on_link_click(sound)
    except:
        var1.set(f"{txt} is not in word_list.")


def prefix(txt):
    """ 前缀匹配 """
    global var1, headwords
    try:
        type(headwords)
    except NameError:
        print('headwords is undefined.')
        return
    if len(txt) > 2:
        listbox.delete(0, tk.END)
        word = txt.strip().lower() # 字母变小写
        for hw in headwords:
            hws = hw.decode().lower()
            if hws.startswith(word):
                listbox.insert(tk.END, hw.decode())
    else:
        var1.set(f"{txt} input too short")    

def sound(url):
    """ 处理<a>链接点击事件 """
    print(url)
    if url.startswith("http://"):
        frame.load_url(url)
        frame.on_link_click(sound)
    elif url.startswith("entry://"):
        query1(url[8:])
    elif url.startswith("sound://"):
        mp3file = 'data' + url[7:]
        mplay(mp3file)
    elif url.startswith('#'):
        frame.skim(url)  #anchor
    else:
        pass

def selected(self):
    """ 选择列表框 """
    try:
        index = listbox.curselection()
        txt = listbox.get(index,last=None)
        query1(txt)
    except:
        print('listbox index is null.')

def search():
    """ 访问http://localhost:???? """
    url = entry.get()
    if url.startswith('http://'):
        frame.load_url(url)
        frame.on_link_click(sound)
        return

# main()
root = tk.Tk()
root.title("查询英汉词典")
root.geometry("1000x500")
root.resizable(width=True, height=False)
# 输入框布局
frame1 = tk.Frame(root, width=80, height=30)
frame1.pack(side="top")
entry = tk.Entry(frame1, width=50)
entry.pack(side="left", padx=5, pady=2)
entry.bind("<Return>", query) # 按下回车,执行查单词
button1 = tk.Button(frame1, text="选择词典", command=open_mdx)
button1.pack(side="left", padx=5, pady=2)
button2 = tk.Button(frame1, text="TTS读单词", command=speak)
button2.pack(side="left", padx=5, pady=2)
button3 = tk.Button(frame1, text="前缀查找", command=search)
button3.pack(side="left", padx=5, pady=2)
# 退出按钮
quit_btn = tk.Button(frame1, text="退出", fg="red", command=root.quit)
quit_btn.pack(side="right", padx=5, pady=2)
# 显示栏
var1 = tk.StringVar()
label = tk.Label(root,textvariable=var1,fg="purple", font="Song 12")
var1.set("请先选择词典")
label.pack()
# 列表框
listbox = tk.Listbox(root, width=25, font="Song 12")
listbox.bind('<<ListboxSelect>>', selected)
listbox.pack(side="left", fill='both')
#create HTML browser
frame = HtmlFrame(root, messages_enabled=False) # False:关闭debug消息
frame.pack(side="right", fill="both", expand=True, padx=5, pady=2)

root.mainloop()

可以先解压.mdd文件:python -m readmdict -x  your.mdd

运行 python tk_read_mdict.py

from tkinterweb import HtmlFrame
help(HtmlFrame)

 |  load_file(self, file_url, decode=None, force=False)
 |      Load a locally stored file from the specified path
 |
 |  load_form_data(self, url, data, method='GET', decode=None)
 |      Load a webpage using form data
 |
 |  load_html(self, html_source, base_url=None)
 |      Reset parser and send html code to it
 |
 |  load_url(self, url, decode=None, force=False)
 |      Load a website (https:// or http://) or a file (file://) from the specified URL.
 |      We use threading here to prevent the GUI from freezing while fetching the website.

关注这一句:  frame.on_link_click(sound)

def sound(url):
    """ 处理<a>链接点击事件 """
    print(url)
    if url.startswith("http://"):
        frame.load_url(url)
        frame.on_link_click(sound)
    elif url.startswith("entry://"):
        query1(url[8:])
    elif url.startswith("sound://"):
        mp3file = 'data' + url[7:]
        mplay(mp3file)
    elif url.startswith('#'):
        frame.skim(url)  #anchor
    else:
        pass


tkinterWeb offers bindings for the Tkhtml3 widget, 可惜 Tkhtml3 不支持 javascript.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python:tkinterweb 简单又好用的 htmlview 组件 的相关文章

  • 如何计算 pandas datetime 对象的均值和方差?

    如何计算 YYYY MM DD 形式的 python 日期时间对象的汇总统计数据 均值和标准差 我想对具有不同 ID 的不同日期时间对象组执行此操作 数据如下 import datetime as dt df pd DataFrame Da
  • 类的 IPython 表示

    我正在使用我创建的模块尝试 IPython 但它没有显示类对象的实际表示 相反 它显示类似的内容 TheClass module TheClass name I heavily在这个模块中使用元类 我有真正有意义的类表示 应该向用户显示 是
  • Pandas set_levels,如何避免标签排序?

    我使用时遇到问题set levels多索引 from io import StringIO txt Name Height Age Metres A 1 25 B 95 1 df pd read csv StringIO txt heade
  • Gunicorn 工作人员无论如何都会超时

    我正在尝试通过gunicorn运行一个简单的烧瓶应用程序 但是无论我做什么 我的工作人员都会超时 无论是否有针对应用程序的活动 工作人员在我设置任何内容后总是会超时timeout值到 是什么导致它们超时 当我发出请求时 请求成功通过 但工作
  • 如何在 __init__ 中使用await设置类属性

    我如何定义一个类await在构造函数或类体中 例如我想要的 import asyncio some code class Foo object async def init self settings self settings setti
  • VSCode Settings.json 丢失

    我正在遵循教程 并尝试将 vscode 指向我为 Scrapy 设置的虚拟工作区 但是当我在 VSCode 中打开设置时 工作区设置 选项卡不在 用户设置 选项卡旁边 我还尝试通过以下方式手动转到文件 APPDATA Code User s
  • 如何从Python中的函数返回多个值? [复制]

    这个问题在这里已经有答案了 如何从Python中的函数返回多个变量 您可以用逗号分隔要返回的值 def get name you code return first name last name 逗号表示它是一个元组 因此您可以用括号将值括
  • Python 3d 绘图设置固定色阶

    我正在尝试绘制两个 3d 数组 第一个数组的 z 值在范围内 0 15 0 15 第二个来自 0 001 0 001 当我绘图时 色标自动遵循数据范围 如何设置自定义比例 我不想看到 0 001 的浅色 而应该看到 0 15 的浅色 如何修
  • 打印数字时添加千位分隔符[重复]

    这个问题在这里已经有答案了 我真的不知道这个问题的 名称 所以它可能是一个不正确的标题 但问题很简单 如果我有一个数字 例如 number 23543 second 68471243 我想要它使print 像这样 23 54368 471
  • 矩形函数的数值傅里叶变换

    本文的目的是通过一个众所周知的分析傅里叶变换示例来正确理解 Python 或 Matlab 上的数值傅里叶变换 为此 我选择矩形函数 这里报告了它的解析表达式及其傅立叶变换https en wikipedia org wiki Rectan
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 从 Powershell 脚本安装 Python

    当以管理员身份从 PowerShell 命令行运行以下命令时 可以在 Windows 11 上成功安装 Python c temp python 3 11 4 amd64 exe quiet InstallAllUsers 0 Instal
  • 当字段是数字时怎么说...在 mongodb 中匹配?

    所以我的结果中有一个名为 城市 的字段 结果已损坏 有时它是一个实际名称 有时它是一个数字 以下代码显示所有记录 db zips aggregate project city substr city 0 1 sort city 1 我需要修
  • 尽管我已在 python ctypes 中设置了信号处理程序,但并未调用它

    我尝试过使用 sigaction 和 ctypes 设置信号处理程序 我知道它可以与python中的信号模块一起使用 但我想尝试学习 当我向该进程发送 SIGTERM 时 但它没有调用我设置的处理程序 只打印 终止 为什么它不调用处理程序
  • 如何将 GAE 中一种 Kind 中的所有实体复制到另一种 Kind 中,而无需显式调用每个属性

    我们如何使用function clone entity 如中所述在 Python 中复制 Google App Engine 数据存储中的实体 而无需在 编译 时知道属性名称 https stackoverflow com question
  • 如何使用 AWS Lambda Python 读取 AWS S3 存储的 Word 文档(.doc 和 .docx)文件内容?

    我的场景是 我尝试使用 python 实现从 Aws Lambda 读取 AWS 存储的 S3 word 文档 doc 和 docx 文件内容 下面的代码是我使用的 我的问题是我可以获取文件名 但无法读取内容 def lambda hand
  • pandas.read_csv 将列名移动一倍

    我正在使用位于的 ALL zip 文件here http www fec gov disclosurep PDownload do 我的目标是用它创建一个 pandas DataFrame 但是 如果我跑 data pd read csv
  • python 对浮点数进行不正确的舍入

    gt gt gt a 0 3135 gt gt gt print 3f a 0 314 gt gt gt a 0 3125 gt gt gt print 3f a 0 312 gt gt gt 我期待 0 313 而不是 0 312 有没有
  • 如何将Python3设置为Mac上的默认Python版本?

    有没有办法将 Python 3 8 3 设置为 macOS Catalina 版本 10 15 2 上的默认 Python 版本 我已经完成的步骤 看看它安装在哪里 ls l usr local bin python 我得到的输出是这样的
  • JSON:TypeError:Decimal('34.3')不是JSON可序列化的[重复]

    这个问题在这里已经有答案了 我正在运行一个 SQL 查询 它返回一个小数列表 当我尝试将其转换为 JSON 时 出现类型错误 查询 res db execute SELECT CAST SUM r SalesVolume 1000 0 AS

随机推荐

  • Vue常见问题——Vue路由跳转、切换、返回页面不刷新问题

    前言 最近用iview admin做后台管理系统 遇到了个问题 列表页面点击进入详情页面编辑 编辑完成自动跳转到列表页 需要页面重新刷新请求列表 后管就是这么简单粗暴 然并卵 再次回到列表页页面不会重新刷新 问题很好解决 因为iview a
  • 梦三国解析服务器spl文件头失败,流沙恐遭降级?《梦三国2》MPL夏季赛第二轮激战全面开启...

    逐梦巅峰 为荣耀而战 2020 梦三国2 职业联赛 简称 MPL 夏季常规赛第一轮较量于上周正式结束 风月战队后来居上 通过6小局连胜将战队积分累积至14分 积分排名连跳3级成功登顶第四周积分榜首之位 常规赛半程结束 让我们快速回顾第四周的
  • 挂机宝怎么搭建php网站,如何使用挂机宝搭建网站?挂机宝建站教程

    教程简介 安逸资源网小编现在教你们怎么使用挂机宝搭建网站 这一教程适用于所有windows系统笔记本或挂机宝qq代挂网站怎么搭建 废话我就不多说了 看到你们这么热爱学习技术的份上就直接上教程吧 第一步 首先我们先打算一台挂机宝 没有的可以去
  • 【Web】go管理配置神器 viper库

    建议看官方文档 viper 库的作用 viper适用与go应用程序中处理多种格式的配置文件 如 YAML JSON TOML 等 它支持 设置默认值 从 JSON TOML YAML HCL envfile 和 Java 属性配置文件中读取
  • C++实现矩阵压缩存储与(快速)转置

    注意 以下所有代码均在VS2010环境下运行测试 了解了C语言以后 我们都知道 要存储一个矩阵 用一个二维数组即可实现 今天 由我来带领大家玩点新鲜的 对矩阵进行压缩存储并对其进行转置 一 对称矩阵及对称矩阵的压缩存储 1 什么是对称矩阵
  • 超详细、超完整的C++教程(算是吧)

    C 是一种高级编程语言 它被广泛应用于软件开发 游戏制作 嵌入式系统等领域 本文将为读者提供一份超详细 超完整的C 教程 帮助初学者掌握C 的基础知识 同时给出十个实例 并一一解释分析 最后 我们将为读者提供一道编程题 并给出解答 目录 第
  • Openwrt安装python问题

    1 tini依赖函数找不到 需要禁用docker compose 2 pip 19版本过低 需要将pip更新到21 3 pip install upgrade pip staging dir hostpkg bin python3 8 m
  • Ubuntu 安装 Visual Studio Code 搭建 C++ 开发环境教程

    Ubuntu 安装 Visual Studio Code 搭建 C 开发环境教程 一 Ubuntu 安装 Visual Studio Code 1 下载 1 在 Ubuntu Software 中下载安装 2 Visual Studio 官
  • 【推荐】10本黑客入门必看的书籍

    前言 书籍介绍黑客入门的基本知识和必备技能 帮助您理解黑客攻击的原理和方法 并提供有效的防御策略 1 白帽子讲Web安全 作者 吴翰清 介绍了常见的Web安全漏洞和攻击技术 并提供了相应的防御策略 2 Metasploit渗透测试指南 作者
  • shell脚本之检索某url中所有文件的内容

    前言 cve 官网或者工信部会发布一些 cve 漏洞 可以看到该漏洞在某次 commit 提交代码后修复的 可以通过检索 kernel org 中所有内核版本的 ChangeLog 文件中是否包含该 commit 来判断漏洞影响的内核版本
  • copyTo 使用方法

    原地址 https blog csdn net qq 36930777 article details 78256739 openCV中image copyTo 有两种形式 1 image copyTo imageROI 作用是把image
  • 2.4.5Qt之plainTextEdit 文本编辑器dial刻度盘spinBox整数计数器QDoubleSpinBox浮点计数器QSlider滑块基础知识

    Qt之plainTextEdit 文本编辑器dial刻度盘spinBox整数计数器QDoubleSpinBox浮点计数器QSlider滑块基础知识 文章目录 Qt之plainTextEdit 文本编辑器dial刻度盘spinBox整数计数器
  • 刷脸支付的广泛应用观望态势势会越来越少

    支付宝 微信支付 中国银联三大巨头都相继推出自己的刷脸支付产品 并对刷脸支付实行大力的推广扶持政策 刷脸支付较当下流行的扫码支付更加便捷 资金更安全 而且还有马云 马化腾多次站台宣传 想不火都难 支付宝宣布其刷脸支付已经具备商业化能力并逐渐
  • 解决ModuleNotFoundError: No module named ‘numpy.core._multiarray_umath‘的方法

    问题 导入tensorflow时报错ModuleNotFoundError No module named numpy core multiarray umath 异常信息如下所示 分析 NumPy是使用Python进行科学计算的基础软件包
  • GPU服务器租用阿里云和腾讯云对比以及学生GPU按量付费攻略

    学生如何选择GPU服务器 哪家GPU服务器 腾讯云GPU服务器和阿里云GPU对比 GPU服务器可以选择按量付费计费模式 用的时候创建一台按量GPU实例 不用的时候释放掉 这样比较划算 腾讯云百科来详细说下哪家GPU服务器划算以及按量付费GP
  • 兼顾测试功能的API文档管理工具:Swagger与RAP2

    常规的开发流程通常为 后端提供API文档 前后端各自实现 联调测试 这里经常遇到的两个问题 文档如何维护 一方实现后 需要等另一方进行联调 对于文档的维护 常规的API文档管理工具都具备文档的创建 修改 共享 版本记录等 差别不大 而对于联
  • Linux MMC驱动架构浅析

    Linux MMC驱动架构浅析 MMC驱动模型 Linux内核设计了MMC子系统 用于管理MMC SD等设备 MMC SD存储设备是一种典型的块设备 MMC子系统的框架结构如下图所示 块设备 MMC BLOCK 块设备的相关驱动 即实现块设
  • Prometheus + Grafana 监控SpringBoot项目

    文章目录 Dubbo Prometheus Grafana 监控SpringBoot项目 方式1 侵入式 通过修改spring boot代码实现 准备镜像 Prometheus 搭建 Grafana 搭建 Spring Boot程序 配置g
  • java_时间戳与Date_相互转化

    1 时间戳的定义 时间戳是指文件属性里的创建 修改 访问时间 数字时间戳技术是数字签名技术一种变种的应用 在电子商务交易文件中 时间是十分重要的信息 在书面合同中 文件签署的日期和签名一样均是十分重要的防止文件被伪造和篡改的关键性内容 数字
  • python:tkinterweb 简单又好用的 htmlview 组件

    tkinterweb 是简单又好用的 webview 组件 也可用来显示本地 html文件 pip install tkinterweb pip install readmdict 参见 使用Python调用mdx字典文件进行查词 安装 M