Python 可以在Tkinter中呈现HTML吗?
我有一张地图,它被保存为Python 可以在Tkinter中呈现HTML吗?,python,html,tkinter,Python,Html,Tkinter,我有一张地图,它被保存为html文件 有没有办法用tkinter在应用程序中显示它 我看到了一些关于tkhtml的答案,但我发现关于它的信息很少。如果有人可以请给我一个光,以及如何和在哪里瞄准我的代码的见解 谢谢不,在tkinter应用程序中没有显示html的好方法 自2008年以来,Tkhtml没有看到任何重大发展,也从未走出早期的阿尔法阶段 据我所知,tkhtml的官方源代码就在这个存储库中:我已经使用@j_4321提供的 只需pip3安装tkinterhtml 从包装上看: 请求并呈现它
html
文件
有没有办法用tkinter在应用程序中显示它
我看到了一些关于tkhtml的答案,但我发现关于它的信息很少。如果有人可以请给我一个光,以及如何和在哪里瞄准我的代码的见解
谢谢不,在tkinter应用程序中没有显示html的好方法 自2008年以来,Tkhtml没有看到任何重大发展,也从未走出早期的阿尔法阶段
据我所知,tkhtml的官方源代码就在这个存储库中:我已经使用@j_4321提供的 只需
pip3安装tkinterhtml
从包装上看:
请求并呈现它
希望有帮助:)是的,您可以在tkinter中嵌入HTML并打开完整的网页(甚至可以使用CSS和javascript)。使用,您可以在tk窗口中嵌入一个成熟的Chromium浏览器。下面是一个显示本地HTML文件的工作示例(在用#todo注释的行中更改HTML文件位置) 2020年8月更新:这适用于Python 2.7/3.4/3.5/3.6/3.7 更新2021年3月现在还支持Python 3.8和3.9
#使用Tkinter工具包嵌入CEF Python浏览器的示例。
#这个示例有两个小部件:导航栏和浏览器。
#
#注意:这个例子经常在Mac上崩溃(Python 2.7,Tk 8.5/8.6)
#在初始应用程序加载期间,使用该消息:
#“分段错误:11”。报告为第309期。
#
#测试配置:
#-Windows/Mac上的Tk 8.5
#-Linux上的Tk 8.6
#-CEF Python v55.3+
#
#Linux上的已知问题:键入url时,鼠标必须位于url上方
#否则键盘焦点丢失(问题#255
#和发行#284)。
从cefpython3导入cefpython作为cef
导入ctypes
尝试:
将tkinter作为tk导入
除恐怖外:
将Tkinter作为tk导入
导入系统
导入操作系统
导入平台
将日志记录导入为\u日志记录
#修复PyCharm提示警告
WindowUtils=cef.WindowUtils()
#平台
WINDOWS=(platform.system()=“WINDOWS”)
LINUX=(platform.system()=“LINUX”)
MAC=(platform.system()==“Darwin”)
#全球的
logger=\u logging.getLogger(“tkinter\uu.py”)
#常数
#Tk 8.5不支持png图像
IMAGE_EXT=“.png”如果tk.TkVersion>8.5 else“.gif”
类大型机(tk.Frame):
定义初始化(自,根):
self.browser\u frame=无
self.navigation\u bar=无
#根
根几何(“900x640”)
tk.Grid.rowconfigure(根,0,权重=1)
tk.Grid.columnconfigure(根,0,权重=1)
#主机
tk.Frame.\uuuu init\uuuu(self,root)
self.master.title(“Tkinter示例”)
self.master.protocol(“WM\u删除\u窗口”,self.on\u关闭)
self.master.bind(“,self.on\u root\u configure)
self.setup_图标()
self.bind(“,self.on_configure”)
self.bind(“,self.on\u focus\u in)
self.bind(“,self.on\u focus\u out)
#导航栏
self.navigation\u bar=导航栏(self)
self.navigation\u bar.grid(行=0,列=0,
粘性=(tk.N+tk.S+tk.E+tk.W))
tk.Grid.rowconfigure(self,0,weight=0)
tk.Grid.columnconfigure(self,0,weight=0)
#浏览器框架
self.browser\u frame=BrowserFrame(self,self.navigation\u栏)
self.browser\u frame.grid(行=1,列=0,
粘性=(tk.N+tk.S+tk.E+tk.W))
tk.Grid.rowconfigure(self,1,weight=1)
tk.Grid.columnconfigure(self,0,weight=1)
#打包主机
self.pack(fill=tk.BOTH,expand=tk.YES)
根目录上的def配置(自身):
logger.debug(“MainFrame.on\u root\u configure”)
如果self.u框架:
self.browser\u frame.on\u root\u configure()
def on_配置(自身、事件):
logger.debug(“MainFrame.on_configure”)
如果self.u框架:
宽度=事件宽度
高度=事件高度
如果self.navigation\u栏:
高度=高度-self.navigation\u bar.winfo\u height()
主机上的self.browser\u frame.on\u配置(宽度、高度)
def on_focus_in(自身)中的定义:
logger.debug(“MainFrame.on\u focus\u in”)
def on_focus_out(自聚焦):
logger.debug(“MainFrame.on\u focus\u out”)
def on_关闭(自身):
如果self.u框架:
self.browser\u frame.on\u root\u close()
self.master.destroy()
def get_浏览器(自身):
如果self.u框架:
返回self.browser\u frame.browser
一无所获
def get_浏览器_框架(自身):
如果self.u框架:
返回self.u帧
一无所获
def设置图标(自身):
resources=os.path.join(os.path.dirname(_文件__),“resources”)
icon\u path=os.path.join(参考资料,“tkinter”+IMAGE\u EXT)
如果os.path.存在(图标路径):
self.icon=tk.PhotoImage(文件=icon\u路径)
#无检查PyProtectedMember
self.master.call(“wm”,“iconphoto”,self.master.\w,self.icon)
类浏览器框架(tk.Frame):
定义初始化(自、主、导航栏=无):
self.navigation\u bar=导航\u bar
自动关闭=错误
self.browser=无
tk.Frame.\uuuuu init\uuuuuuu(自,主)
self.bind(“,self.on\u focus\u in)
self.bind(“,self.on\u focus\u out)
self.bind(“,self.on_configure”)
self.focus_set()
def嵌入式浏览器(自身):
window_info=cef.WindowInfo()
rect=[0,0,self.winfo_width(),self.winfo_height()]
window\u info.SetAsChild(self.get\u window\u handle(),rect)
self.browser=cef.CreateBrowserSync(窗口信息,
url=”file:///J:\q、 htm”)待办事项
断言self.browser
self.browser.SetClientHandler(LoadHandler(self))
self.browser.SetClientHandle
from tkinterhtml import HtmlFrame
import tkinter as tk
root = tk.Tk()
frame = HtmlFrame(root, horizontal_scrollbar="auto")
frame.set_content("<html></html>")
frame.set_content(urllib.request.urlopen("http://thonny.cs.ut.ee").read().decode())
# Example of embedding CEF Python browser using Tkinter toolkit.
# This example has two widgets: a navigation bar and a browser.
#
# NOTE: This example often crashes on Mac (Python 2.7, Tk 8.5/8.6)
# during initial app loading with such message:
# "Segmentation fault: 11". Reported as Issue #309.
#
# Tested configurations:
# - Tk 8.5 on Windows/Mac
# - Tk 8.6 on Linux
# - CEF Python v55.3+
#
# Known issue on Linux: When typing url, mouse must be over url
# entry widget otherwise keyboard focus is lost (Issue #255
# and Issue #284).
from cefpython3 import cefpython as cef
import ctypes
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
import sys
import os
import platform
import logging as _logging
# 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("tkinter_.py")
# Constants
# Tk 8.5 doesn't support png images
IMAGE_EXT = ".png" if tk.TkVersion > 8.5 else ".gif"
class MainFrame(tk.Frame):
def __init__(self, root):
self.browser_frame = None
self.navigation_bar = None
# Root
root.geometry("900x640")
tk.Grid.rowconfigure(root, 0, weight=1)
tk.Grid.columnconfigure(root, 0, weight=1)
# MainFrame
tk.Frame.__init__(self, root)
self.master.title("Tkinter example")
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)
# NavigationBar
self.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)
# BrowserFrame
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))
tk.Grid.rowconfigure(self, 1, weight=1)
tk.Grid.columnconfigure(self, 0, weight=1)
# Pack MainFrame
self.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.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, _):
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.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 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 PyProtectedMember
self.master.call("wm", "iconphoto", self.master._w, self.icon)
class BrowserFrame(tk.Frame):
def __init__(self, master, navigation_bar=None):
self.navigation_bar = navigation_bar
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="file:///J:\q.htm") #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:
# On Mac window id is an invalid negative value (Issue #308).
# This is kind of a dirty hack to get window handle using
# PyObjC package. If you change structure of windows then you
# need to do modifications here as well.
# noinspection PyUnresolvedReferences
from AppKit import NSApp
# noinspection PyUnresolvedReferences
import objc
# Sometimes there is more than one window, when application
# didn't close cleanly last time Python displays an NSAlert
# window asking whether to Reopen that window.
# noinspection PyUnresolvedReferences
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, _):
logger.debug("BrowserFrame.on_focus_in")
if self.browser:
self.browser.SetFocus(True)
def on_focus_out(self, _):
logger.debug("BrowserFrame.on_focus_out")
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):
# Clear browser references that you keep anywhere in your
# code. All references must be cleared for CEF to shutdown cleanly.
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, **_):
logger.debug("FocusHandler.OnTakeFocus, next={next}"
.format(next=next_component))
def OnSetFocus(self, source, **_):
logger.debug("FocusHandler.OnSetFocus, source={source}"
.format(source=source))
return False
def OnGotFocus(self, **_):
"""Fix CEF focus issues (#255). Call browser frame's focus_set
to get rid of type cursor in url entry widget."""
logger.debug("FocusHandler.OnGotFocus")
self.browser_frame.focus_set()
class NavigationBar(tk.Frame):
def __init__(self, master):
self.back_state = tk.NONE
self.forward_state = tk.NONE
self.back_image = None
self.forward_image = None
self.reload_image = None
tk.Frame.__init__(self, master)
resources = os.path.join(os.path.dirname(__file__), "resources")
# Back button
back_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)
# Forward button
forward_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)
# Reload button
reload_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)
# Url entry
self.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)
# Update state of buttons
self.update_state()
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, _):
"""Fix CEF focus issues (#255). See also FocusHandler.OnGotFocus."""
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.DISABLED
if self.forward_state != tk.DISABLED:
self.forward_button.config(state=tk.DISABLED)
self.forward_state = tk.DISABLED
self.after(100, self.update_state)
return
if browser.CanGoBack():
if self.back_state != tk.NORMAL:
self.back_button.config(state=tk.NORMAL)
self.back_state = tk.NORMAL
else:
if self.back_state != tk.DISABLED:
self.back_button.config(state=tk.DISABLED)
self.back_state = tk.DISABLED
if browser.CanGoForward():
if self.forward_state != tk.NORMAL:
self.forward_button.config(state=tk.NORMAL)
self.forward_state = tk.NORMAL
else:
if self.forward_state != tk.DISABLED:
self.forward_button.config(state=tk.DISABLED)
self.forward_state = tk.DISABLED
self.after(100, self.update_state)
if __name__ == '__main__':
logger.setLevel(_logging.INFO)
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"
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
root = tk.Tk()
app = MainFrame(root)
# Tk must be initialized before CEF otherwise fatal error (Issue #306)
cef.Initialize()
app.mainloop()
cef.Shutdown()