Repository: Andereoo/TkinterWeb
Branch: main
Commit: 4a317a4c5d88
Files: 43
Total size: 535.1 KB
Directory structure:
gitextract_67ltj4rn/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── .readthedocs.yaml
├── LICENSE.md
├── MANIFEST.in
├── README.md
├── docs/
│ ├── Makefile
│ ├── make.bat
│ ├── requirements.txt
│ └── source/
│ ├── _static/
│ │ ├── banner.png~
│ │ └── custom.css
│ ├── api/
│ │ ├── extensions.rst
│ │ ├── htmldocument.rst
│ │ ├── htmlframe.rst
│ │ ├── jsengine.rst
│ │ ├── notebook.rst
│ │ ├── tkinterweb.rst
│ │ └── tkinterweb_api.rst
│ ├── api.rst
│ ├── caret.rst
│ ├── compatibility.rst
│ ├── conf.py
│ ├── dom.rst
│ ├── faq.rst
│ ├── geometry.rst
│ ├── index.rst
│ ├── javascript.rst
│ ├── shrink.rst
│ ├── upgrading.rst
│ └── usage.rst
├── examples/
│ └── TkinterWebBrowser.py
├── setup.py
├── tkinterweb/
│ ├── __init__.py
│ ├── bindings.py
│ ├── dom.py
│ ├── extensions.py
│ ├── handlers.py
│ ├── htmlwidgets.py
│ ├── imageutils.py
│ ├── js.py
│ ├── subwidgets.py
│ └── utilities.py
└── tools/
└── preparewheels.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
buy_me_a_coffee: andereoo
================================================
FILE: .gitignore
================================================
build/
tkinterweb/__pycache__/
tkinterweb/resources/
tkinterweb.egg-info
================================================
FILE: .readthedocs.yaml
================================================
version: "2"
build:
os: "ubuntu-22.04"
tools:
python: "3.10"
python:
install:
- requirements: docs/requirements.txt
sphinx:
configuration: docs/source/conf.py
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2021-2025 Andrew Clarke
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: MANIFEST.in
================================================
recursive-include tkinterweb/resources *
================================================
FILE: README.md
================================================




**
Fast and lightweight web browser, rich text, and app design widgets for Tkinter.
**
## Overview
**TkinterWeb adds HTML and CSS rendering capabilities to Tkinter widgets.**
Common use cases include displaying help files, documentation, and other HTML content, rendering images (including SVG), building rich-text editors, designing apps with HTML templates, and creating more modern-looking interfaces, with advanced styling and even round buttons!
All [major operating systems](https://tkinterweb.readthedocs.io/en/latest/compatibility.html#a-note-on-tkhtml-binaries) running Python 3.2+ are supported.
## Usage
**TkinterWeb provides:**
* A [frame widget](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html) to display and edit websites, help files, RSS feeds, and any other styled HTML in Tkinter.
* A [label widget](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html#tkinterweb.HtmlLabel) that can display styled HTML.
* A [text widget](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html#tkinterweb.HtmlText) that allows the user to edit styled HTML.
**TkinterWeb can be used in any Tkinter application to display and edit websites, help pages, documentation, and much more! Here is an example:**
```
import tkinter as tk
from tkinterweb import HtmlFrame # import the HtmlFrame widget
root = tk.Tk() # create the Tkinter window
frame = HtmlFrame(root, messages_enabled=True) # create the HtmlFrame widget
frame.load_website("https://tkinterweb.readthedocs.io/en/latest/index.html") # load a website
frame.pack(fill="both", expand=True) # attach the HtmlFrame widget to the window
root.mainloop()
```

See [Getting Started](https://tkinterweb.readthedocs.io/en/latest/usage.html) for more tips and tricks.
## Installation
To install TkinterWeb, simply type `pip install tkinterweb[recommended]` in the command prompt or terminal. That's it!
Or, you can also choose from the following extras: `pip install tkinterweb[html,images,svg,javascript,requests]`. You can also use `pip install tkinterweb[full]` to install all optional dependencies or ``pip install tkinterweb`` to install the bare minimum.
## Dependencies
**TkinterWeb offers bindings and extensions to a modified version of the Tkhtml3 widget from [http://tkhtml.tcl.tk](https://web.archive.org/web/20250219233338/http://tkhtml.tcl.tk/). Tkinter and the [TkinterWeb-Tkhtml](https://pypi.org/project/tkinterweb-tkhtml/) package are required.**
I also **strongly** recommended installing the following:
* [TkinterWeb-Tkhtml-Extras](https://pypi.org/project/tkinterweb-tkhtml-extras/) (for better HTML/CSS support and bug fixes)
* [PIL](https://pillow.readthedocs.io/) (for better image support)
* [PIL.ImageTk](https://pillow.readthedocs.io/en/stable/reference/ImageTk.html)
You can also choose from the following list for extra functionality:
* [Brotli](https://github.com/google/brotli) (for faster page loads on some sites)
* [PythonMonkey](http://pythonmonkey.io/) (for basic JavaScript support)
* [CairoSVG](https://cairosvg.org/) or [PyGObject](https://pygobject.gnome.org/) (for SVG support)
Pip will automatically install dependencies when installing TkinterWeb. PIL.ImageTk should be automatically installed with PIL but might need to installed separately on some systems.
## API Documentation
> [!WARNING]
> The API changed significantly in version 4.0.0. See [the changelog](https://tkinterweb.readthedocs.io/en/latest/upgrading.html) for details.
**Documentation and additional information on built-in classes can be found in the corresponding API reference pages:**
* [`tkinterweb.Demo`](https://tkinterweb.readthedocs.io/en/latest/usage.html#installation)
* [`tkinterweb.HtmlFrame`](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html)
* [`tkinterweb.HtmlLabel`](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html#tkinterweb.HtmlLabel)
* [`tkinterweb.HtmlText`](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html#tkinterweb.HtmlText)
* [`tkinterweb.HtmlParse`](https://tkinterweb.readthedocs.io/en/latest/api/htmlframe.html#tkinterweb.HtmlParse)
* [`tkinterweb.TkinterWeb`](https://tkinterweb.readthedocs.io/en/latest/api/tkinterweb.html)
* [`tkinterweb.Notebook`](https://tkinterweb.readthedocs.io/en/latest/api/notebook.html) (a Tkhtml-compatible drop-in replacement for `ttk.Notebook`)
## FAQs
See [Frequently Asked Questions](https://tkinterweb.readthedocs.io/en/latest/faq.html).
## Webpage Compatability
**HTML & CSS:**
* TkinterWeb supports HTML 4.01 and CSS 2.1. A full list of supported CSS declarations can be found at [http://tkhtml.tcl.tk/support.html](https://web.archive.org/web/20250325123206/http://tkhtml.tcl.tk/support.html).
* Most CSS pseudo-elements, such as `:hover` and `:active` are also supported.
* On 64-bit Windows and Linux, if the [TkinterWeb-Tkhtml-Extras](https://pypi.org/project/tkinterweb-tkhtml-extras/) is installed, HTML5 tags and some extra CSS properties (including `border-radius` and `overflow-x`) and cursors are also supported. To use these features on all other platforms, you will simply need to compile Tkhtml yourself. Visit and clone https://github.com/Andereoo/TkinterWeb-Tkhtml. Then run `python compile.py --install`.
**JavaScript:**
* Javascript only partly supported at the moment.
* To use JavaScript, PythonMonkey must be installed.
* It is also possible for the user to connect their own JavaScript interpreter or manipulate the document through Python.
* See [Using JavaScript](https://tkinterweb.readthedocs.io/en/latest/javascript.html) for more information and [DOM Manipulation with TkinterWeb](https://tkinterweb.readthedocs.io/en/latest/dom.html) for information on manipulating the document through Python.
**Images:**
* TkinterWeb supports nearly 50 different image types through PIL.
* In order to load Scalable Vector Graphic images, CairoSVG, both PyCairo and PyGObject, or both PyCairo and Rsvg must also be installed.
## Support & Donations
**☕ If you’d like to support ongoing development and maintenance, please consider supporting this project by [buying me a coffee](https://buymeacoffee.com/andereoo). Any amount is hugely appreciated!**
This project is released under the [MIT License](./LICENSE.md) and is free to use, including for commercial purposes.
If you use this project in a commercial product or derive financial benefit from it, please kindly consider supporting its development with a donation. This helps cover maintenance time and ongoing improvements, which in turn will improve your own software!
## Contributing
**The best ways to contribute to this project are by submitting a [bug report](https://github.com/Andereoo/TkinterWeb/issues/new) to report bugs or suggest new features, or by submitting a [pull request](https://github.com/Andereoo/TkinterWeb/pulls) to offer fixes. Your help makes TkinterWeb become more stable and full-featured!**
Please check the [FAQs](https://tkinterweb.readthedocs.io/en/latest/faq.html) and [closed bugs](https://github.com/Andereoo/TkinterWeb/issues?q=is%3Aissue) before submitting a bug report to see if your question as already been answered.
## Credits
**TkinterWeb is powered by the [Tkhtml project](https://web.archive.org/web/20250219233338/http://tkhtml.tcl.tk/).**
Special thanks to [Christopher Chavez](https://github.com/chrstphrchvz), [Zamy846692](https://github.com/Zamy846692), [Jośe Fernando Moyano](https://github.com/jofemodo), [Bumshakalaka](https://github.com/Bumshakalaka), [Trov5](https://github.com/TRVRStash), [Mark Mayo](https://github.com/marksmayo), [Jaedson Silva](https://github.com/jaedsonpys), [Nick Moore](https://github.com/nickzoic), [Leonardo Saurwein](https://github.com/Sau1707), and [Hbregalad](https://github.com/hbregalad) for their code suggestions and pull requests.
Special thanks to [Christopher Chavez](https://github.com/chrstphrchvz), Jan Nijtmans, and everyone else in the tcl-core mailing list for the help making border rounding work on Windows and MacOSX, and to [Zamy846692](https://github.com/Zamy846692) for spearheading experimental Tkhtml development.
Thanks to the [TkinterHtml package](https://bitbucket.org/aivarannamaa/tkinterhtml) for providing the bindings on which this project is based and the [BRL-CAD project](https://github.com/BRL-CAD/brlcad) for providing modifications for Tkhtml on 64-bit Windows.
A huge thanks to everyone else who supported this project by reporting bugs and providing suggestions!
================================================
FILE: docs/Makefile
================================================
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
================================================
FILE: docs/make.bat
================================================
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd
================================================
FILE: docs/requirements.txt
================================================
sphinx==7.1.2
sphinx-rtd-theme==1.3.0rc1
sphinx_design==0.6.1
tkinterweb-tkhtml >= 2.0.0
Pillow >= 10.0.0
================================================
FILE: docs/source/_static/custom.css
================================================
/* This file is used to make tweak the documentation and make it CSS2 compatible.*/
.wy-nav-side {
overflow: hidden !important;
}
.wy-side-nav-search > div.version {
color: #cacaca !important;
}
.wy-side-nav-search, .wy-nav-top, .note .admonition-title, .wy-menu-vertical a:active {
background-color: rgb(77, 122, 77) !important;
}
.wy-nav-content a {
color: rgb(77, 122, 77);
}
.wy-nav-content a:hover {
color: rgb(96, 156, 96);
}
code.literal,
span.literal {
color: rgb(94, 94, 94) !important;
}
.rst-content code.xref,
.rst-content tt.xref,
a .rst-content code,
a .rst-content tt {
color: initial !important
}
.note {
background-color: rgb(230, 238, 230) !important;
}
#rtd-search-form input {
width: 80% !important;
color: black !important;
margin-left: auto;
margin-right: auto;
}
.wy-breadcrumbs .icon-home:before {
content: "Home" !important;
font-family: Lato, proxima-nova, Helvetica Neue, Arial, sans-serif !important;
}
.wy-breadcrumbs .wy-breadcrumbs-aside {
display: none;
}
.wy-side-nav-search {
padding-left: 0 !important;
padding-right: 0 !important;
}
.wy-breadcrumbs .breadcrumb-item {
display: inline !important;
}
.highlight-python,
.highlight-console,
.highlight-default {
border: 1px solid #e1e4e5 !important;
margin: 1px 0 24px !important;
background: #f8f8f8 !important;
width: 100% !important;
}
.highlight pre {
white-space: pre !important;
margin: 0 !important;
padding: 12px !important;
display: block !important;
}
.highlight {
border: none !important;
margin: 0 !important;
}
.sig-object {
display: table !important;
margin: 6px 0 !important;
margin-top: 6px !important;
font-size: 90% !important;
line-height: normal !important;
background: rgb(230, 238, 230) !important;
color: rgb(77, 122, 77) !important;
border-top: 3px solid rgb(101, 145, 101) !important;
padding: 6px !important;
position: relative !important;
}
.sig-object .property,
.sig-object .sig-param,
.sig-object .sig-paren {
font-size: 90% !important;
line-height: normal !important;
color: rgb(77, 122, 77) !important;
}
.sig-object .sig-name,
.sig-object .sig-prename {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, Courier, monospace !important;
color: #000 !important;
}
dd .sig-object {
margin-bottom: 6px !important;
border: none !important;
border-left-width: medium !important;
border-left-style: none !important;
border-left-color: currentcolor !important;
border-left: 3px solid #ccc !important;
background: #f0f0f0 !important;
color: #555 !important;
}
dd .sig-name {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, Courier, monospace !important;
color: #000 !important;
}
dd .property,
dd .sig-param,
dd .sig-paren {
color: inherit !important
}
.rst-footer-buttons {
display: table !important;
width: 100% !important;
}
.rst-footer-buttons .float-left {
display: table-cell !important;
}
.rst-footer-buttons .float-right {
display: table-cell !important;
}
.fa-arrow-circle-right:before {
content: " →" !important;
}
.fa-arrow-circle-left:before {
content: "← " !important;
}
.btn {
border-color: #e1e4e5 !important;
padding: 6px 12px !important;
border-bottom: 2px solid #ccc !important;
box-shadow: none !important;
transition: none !important;
}
.btn:active {
border-top: 2px solid #ccc !important;
padding: 5px 12px 7px !important;
border-bottom-width: 1px !important;
}
.wy-side-nav-search > a {
padding: 0 !important;
margin: 0 !important;
}
.wy-side-nav-search > a:hover {
background: transparent !important;
}
.wy-side-nav-search > a img.logo {
max-width: 250px !important;
margin: 0 !important;
}
.sd-card-header {
display: block;
}
details.sd-dropdown .sd-summary-content p {
cursor: text;
}
details.sd-dropdown summary.sd-summary-title{
padding: .5em .6em .5em 1em !important;
}
.sd-mb-3, .sd-my-3 {
margin-bottom: 16px !important;
}
.sd-card-header, .sd-card {
border-color: #dcdcdc;
border-radius: 4px;
}
.sd-card-body {
padding: 0px 17px !important;
}
.rst-content .section ul, .rst-content .toctree-wrapper ul, .rst-content section ul, .wy-plain-list-disc, article ul {
margin: 12px 0px !important;
}
.sd-card-body > p {
margin: 12px 0px !important;
}
================================================
FILE: docs/source/api/extensions.rst
================================================
TkinterWeb Extensions
=====================
The following objects are extensions to the :class:`~tkinterweb.TkinterWeb` widget and are largely internal. You will likely never need to access them, but they are described here just in case.
The methods described in this page may change at any time without warning. If you are relying on anything here, please let me know so I know to keep compatibility.
.. autoclass:: tkinterweb.extensions.SelectionManager
:members:
.. autoclass:: tkinterweb.extensions.CaretManager
:members:
.. autoclass:: tkinterweb.extensions.EventManager
:members:
.. autoclass:: tkinterweb.extensions.WidgetManager
:members:
.. autoclass:: tkinterweb.extensions.SearchManager
:members:
================================================
FILE: docs/source/api/htmldocument.rst
================================================
Document Object Model Documentation
===================================
.. note::
The API changed significantly in version 4. See :doc:`the changelog <../upgrading>` for details.
The methods described in this page make it easy to modify the appearance and content of a loaded document and manage interaction with the document. For the most part, this page mirrors the core JavaScript DOM API.
.. autoclass:: tkinterweb.dom.HTMLDocument
:members:
.. autoclass:: tkinterweb.dom.HTMLElement
:members:
The following JavaScript event properties are also supported: ``onchange``, ``onclick``, ``oncontextmenu``, ``ondblclick``, ``onload``, ``onmousedown``, ``onmouseenter``, ``onmouseleave``, ``onmousemove``, ``onmouseout``, ``onmouseover``, and ``onmouseup``.
.. autoclass:: tkinterweb.dom.HTMLCollection
:members:
.. autoclass:: tkinterweb.dom.CSSStyleDeclaration
:members:
.. autoclass:: tkinterweb.dom.DOMRect
:members:
Special thanks to `Zamy846692 `_ for the help making this happen!
================================================
FILE: docs/source/api/htmlframe.rst
================================================
HTML Widgets Documentation
==========================
.. note::
The API changed significantly in version 4. See :doc:`the changelog <../upgrading>` for details.
The :class:`~tkinterweb.HtmlFrame` widget is a Tkinter frame that provides additional functionality to the :class:`~tkinterweb.TkinterWeb` widget by adding automatic scrollbars, error handling, and many convenience methods into one embeddable and easy to use widget.
The :class:`~tkinterweb.HtmlFrame` widget is also capable managing other Tkinter widgets, making it easy to combine Tkinter widgets and HTML elements.
.. autoclass:: tkinterweb.HtmlFrame
:members:
This widget also emits the following Tkinter virtual events that can be bound to:
* ``<>``/:py:attr:`utilities.DOWNLOADING_RESOURCE_EVENT`: Generated whenever a new resource is being downloaded.
* ``<>``/:py:attr:`utilities.DONE_LOADING_EVENT`: Generated whenever all outstanding resources have been downloaded. This is generally a good indicator as to when the website is done loading, but may be generated multiple times while loading a page.
* ``<>``/:py:attr:`utilities.DOM_CONTENT_LOADED_EVENT`: Generated once the page content has loaded. The page may not be done loading, but at this point it is possible to interact with the DOM.
* ``<>``/:py:attr:`utilities.URL_CHANGED_EVENT`: Generated whenever the widget's url changes or redirects. Use :attr:`.HtmlFrame.current_url` to get the url.
* ``<>``/:py:attr:`utilities.ICON_CHANGED_EVENT`: Generated whenever the icon of a webpage changes. Use :attr:`.HtmlFrame.icon` to get the icon.
* ``<>``/:py:attr:`utilities.TITLE_CHANGED_EVENT`: Generated whenever the title of a website or file has changed. Use :attr:`.HtmlFrame.title` to get the title.
* ``<>```/:py:attr:`utilities.FIELD_CHANGED_EVENT`: Generated whenever the content of an interactive element changes.
.. autoclass:: tkinterweb.HtmlLabel
:members:
.. autoclass:: tkinterweb.HtmlText
:members:
.. autoclass:: tkinterweb.HtmlParse
:members:
================================================
FILE: docs/source/api/jsengine.rst
================================================
JavaScript Engine Documentation
===============================
The methods described in this page make it easy to interact with the JavaScript Engine.
.. autoclass:: tkinterweb.js.JSEngine
:members:
================================================
FILE: docs/source/api/notebook.rst
================================================
Notebook Documentation
=======================
The TkinterWeb :class:`~tkinterweb.Notebook` widget should be used in place of :py:class:`ttk.Notebook`, which is incompatable with Tkhtml on 64-bit Windows and crashes when selecting tabs. See https://docs.python.org/3/library/tkinter.ttk.html#notebook for the full API.
.. autoclass:: tkinterweb.Notebook
:members:
This widget also emits the following Tkinter virtual events that can be bound to:
* ``<>``: Generated whenever the selected tab changes.
================================================
FILE: docs/source/api/tkinterweb.rst
================================================
Internals Documentation
=======================
.. toctree ::
:maxdepth: 2
tkinterweb_api
extensions
================================================
FILE: docs/source/api/tkinterweb_api.rst
================================================
Bindings Documentation
======================
.. note::
This API has changed significantly recently. See :doc:`the changelog <../upgrading>` for details.
The following objects offer the core bindings to the Tkhtml3 HTML widget and are largely internal. You will likely never need to access them, but they are described here just in case.
Refer to the `Tkhtml Documentation `_ for more details on some of the commands.
.. autoclass:: tkinterweb.TkinterWeb
:members:
.. autoclass:: tkinterweb.TkHtmlParsedURI
:members:
================================================
FILE: docs/source/api.rst
================================================
API Reference
==============
.. note::
The API changed significantly in version 4. See :doc:`the changelog ` for details.
.. toctree::
:maxdepth: 2
:caption: Available Classes
api/htmlframe
api/htmldocument
api/jsengine
api/notebook
-------------------
.. toctree::
:maxdepth: 3
api/tkinterweb
================================================
FILE: docs/source/caret.rst
================================================
Making Documents Editable
=========================
.. note::
Caret browsing support is new in version 4.8. The :class:`~tkinterweb.HtmlText` widget was made editable in version 4.15. Make sure you are using the latest version of TkinterWeb.
Overview
--------
**TkinterWeb can be used to create a rich text or HTML editor.**
The :class:`~tkinterweb.HtmlText` widget provides a simple HTML editor that can be extended to adapt to the needs of your application.
TkinterWeb also provides a useful API for developers to create their own HTML-based what-you-see-is-what-you-get editor.
These features are new. Please reach out to report a bug, suggest an improvement, or seek support.
Setup
------
To enable caret browsing mode, add ``yourhtmlframe.configure(caret_browsing_enabled=True)`` to your script or add the parameter ``caret_browsing_enabled=True`` when creating your :class:`~tkinterweb.HtmlFrame` or :class:`~tkinterweb.HtmlLabel` widget.
When enabled, a caret will appear once the user clicks on text in the document. Use the methods described below to handle keypresses, or instead use the :class:`~tkinterweb.HtmlText` widget which handles most cases on its own.
How-to
------
Simply create your :class:`~tkinterweb.HtmlText` and start editing!
.. code-block:: python
from tkinterweb import HtmlText
yourhtmlframe = HtmlText(root, messages_enabled=True)
You can also load html, files, and websites. For instance, to create an editable page with a heading, an orange block, and a list, you could use the following:
.. code-block:: python
yourhtmlframe = HtmlText(root, messages_enabled=True)
yourhtmlframe.load_html("""
Hello, world!
Tkinter is so cool.
TkinterWeb is also cool
Python is also cool
""")
.. image:: ./_static/text_widget.png
It's that easy!
You can insert and edit hyperlinks, images, and much more. Click on a hyperlink while pressing the Ctrl key to navigate to it. Like the :class:`~tkinterweb.HtmlFrame` widget, the :class:`~tkinterweb.HtmlText` widget is also scrollable out of the box!
You can also use :meth:`.HtmlText.insert` and :meth:`.HtmlText.delete` to easily modify the document.
Customization
-------------
Everything described below applies to all HTML widgets with caret browsing enabled.
Use :meth:`.HtmlFrame.get_caret_position` to get the caret's position. The element returned will always be a text node.
.. tip::
You can use the methods outlined in the `HTMLElement documentation `_ to get the element's parent if needed. From here you can insert new elements, change the text and much more!
Use :meth:`.HtmlFrame.shift_caret_left` or :meth:`.HtmlFrame.shift_caret_right` to shift the caret left or right.
The following is a simple example showing how to handle keypresses to insert letters and numbers:
.. code-block:: python
def on_keypress(event):
# Get the caret's position
caret_position = yourhtmlframe.get_caret_position()
if caret_position and event.char:
element, text, index = caret_position
# Add the key's character to the element's text
newtext = text[:index] + event.char + text[index:]
# Set the element's text
element.textContent = newtext
# Shift the caret right
yourhtmlframe.shift_caret_right()
yourhtmlframe.bind("", on_keypress)
This works on all HTML widgets.
.. warning::
If using the :class:`~tkinterweb.HtmlText` widget, binding to ```` will remove all default key bindings. Either bind to individual keys as needed or use ``yourhtmlframe.bind("", on_keypress, add="+")``, but keep in mind then both bindings will fire.
.. note::
Most HTML elements collapse spaces. To insert a space into the document's text, it is usually best to use a non-breaking space (``"\xa0"`` or ``" "``).
Use :meth:`.HtmlFrame.set_caret_position` to set the caret's position if you know the element and index you want to place the caret at.
Some extra logic will be needed to handle other types of keypresses. See the :class:`~tkinterweb.HtmlText` source code for inspiration.
.. tip::
When handling backspaces at the start of a node or deletions at the end of a node, it is sometimes useful to find the previous or following text nodes, respectively.
You can get the preceeding or following text nodes by using :meth:`.HtmlFrame.shift_caret_left` or :meth:`.HtmlFrame.shift_caret_right` followed by :meth:`.HtmlFrame.get_caret_position`.
Use :meth:`.HtmlFrame.get_selection_position` to get the position of any selected text and :meth:`.HtmlFrame.clear_selection` to clear the selection.
You may need to set the caret's position after modifying the document.
.. tip::
:meth:`.HtmlFrame.set_caret_position` will raise an error if the element provided has been removed or is empty.
If you need to remove or empty the elements returned by :meth:`.HtmlFrame.get_selection_position` or :meth:`.HtmlFrame.get_caret_position`, you can also get the selection or caret's position relative to the page text content using :meth:`HtmlFrame.get_selection_position(return_elements=False) <.HtmlFrame.get_selection_position>` and :meth:`HtmlFrame.get_caret_position(return_element=False) <.HtmlFrame.get_caret_position>`, respectively.
You can then set the selection or caret's position as usual, providing only indexes (i.e. ``yourhtmlframe.set_selection_position(start_index=5, end_index=10)``.
The following code can be used as a starting point on handling backspaces when text is selected:
.. code-block:: python
def on_backspace(event):
# Get the selection's position and deselect all selected text
selection = yourhtmlframe.get_selection_position()
if selection:
start, end, middle = selection
start_element, start_element_text, start_element_index = start
end_element, end_element_text, end_element_index = end
# Deselect all selected text
d.clear_selection()
# Cut out the selection
start_element.textContent = start_element_text[:start_element_index] + start_element_text[end_element_index:]
if start_element != end_element:
# Delete the end element
end_element.remove()
# Remove each element that is fully selected, and its parent if it is now empty
for element in middle:
parent = element.parentElement
element.remove()
if len(parent.children) == 0:
parent.remove()
# Set the caret's position
yourhtmlframe.set_caret_position(start_element, start_element_index)
yourhtmlframe.bind("", on_backspace)
You can use :meth:`.HtmlFrame.set_selection_position` to set the selection if needed.
-------------------
See the `HtmlFrame documentation `_ for a complete list of supported methods.
Please report bugs or request new features on the `issues page `_.
================================================
FILE: docs/source/compatibility.rst
================================================
System and Webpage Compatibility
================================
System compatibility
--------------------
**TkinterWeb supports all platforms but only ships with precompiled Tkhtml binaries for the most common platforms:**
* x86_64 Windows, Linux, and macOS
* i686 Windows and Linux
* ARM64 Macos and Linux
* ARMv71 Linux
If your system is unsupported, compile and install Tkhtml by visiting and cloning https://github.com/Andereoo/TkinterWeb-Tkhtml. Then run ``python compile.py --install``.
Alternatively, you can install Tkhtml system-wide (i.e. through your system package manager) and then add the parameter :attr:`use_prebuilt_tkhtml=False` when creating your :class:`~tkinterweb.HtmlFrame`, :class:`~tkinterweb.HtmlLabel`, or :class:`~tkinterweb.HtmlText` widget to use the system's Tkhtml. Keep in mind that some features will no longer work.
If you are encountering issues, feel free to submit a bug report or feature request.
The experimental Tkhtml version is not provided as a pre-built binary but can be compiled from the source code at https://github.com/Andereoo/TkinterWeb-Tkhtml/tree/experimental. This version has better cross-platform compatibility, is printable, and introduces support for some new CSS3 properties!
Webpage compatibility
---------------------
**HTML & CSS:**
* TkinterWeb supports HTML 4.01 and CSS 2.1. A full list of supported CSS declarations can be found at `http://tkhtml.tcl.tk/support.html `_.
* Most CSS pseudo-elements, such as ``:hover`` and ``:active`` are also supported.
* On 64-bit Windows and Linux, if the `TkinterWeb-Tkhtml-Extras `_ package is installed, HTML5 tags and some extra CSS properties (including ``border-radius`` and ``overflow-x``) and cursors are also supported. To use these features on all other platforms, you will simply need to compile Tkhtml yourself. Visit and clone https://github.com/Andereoo/TkinterWeb-Tkhtml. Then run ``python compile.py --install``.
**JavaScript:**
* JavaScript partly supported at the moment. See :doc:`javascript` for more information.
* To use JavaScript, `PythonMonkey `_ must be installed.
* It is also possible for the user to connect their own JavaScript interpreter or manipulate the document through Python. See :doc:`javascript` and :doc:`dom` for more information.
**Images:**
* TkinterWeb supports nearly 50 different image types through `PIL `_.
* In order to load Scalable Vector Graphic images, `CairoSVG `_, `PyGObject `_, or both :py:mod:`PyCairo` and :py:mod:`Rsvg` must also be installed.
-------------------
Please report bugs or request new features on the `issues page `_.
================================================
FILE: docs/source/conf.py
================================================
# Configuration file for the Sphinx documentation builder.
# -- Project information
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname((os.path.realpath(__file__))))))
from tkinterweb import __title__, __copyright__, __author__, __version__
project = __title__
copyright = __copyright__
author = __author__
release = ".".join(__version__.split(".")[:2])
version = __version__
# -- General configuration
extensions = [
'sphinx.ext.duration',
'sphinx.ext.doctest',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.intersphinx',
"sphinx_design",
]
intersphinx_mapping = {
'python': ('https://docs.python.org/3/', None),
'sphinx': ('https://www.sphinx-doc.org/en/master/', None),
}
html_logo = "_static/logo.png"
html_theme_options = {"logo_only": True}
templates_path = ['_templates']
html_static_path = ['_static']
html_css_files = ['custom.css']
# -- Options for HTML output
autodoc_member_order = 'bysource'
html_theme = 'sphinx_rtd_theme' # May switch to agogo or alabaster or python_docs_theme
# -- Options for EPUB output
epub_show_urls = 'footnote'
def skip_member(app, what, name, obj, skip, options):
if name == "destroy" and what == "class":
return True
return skip
def setup(app):
app.connect("autodoc-skip-member", skip_member)
================================================
FILE: docs/source/dom.rst
================================================
Manipulating the Page
=====================
.. note::
The API changed significantly in version 4. See :doc:`the changelog ` for details.
Overview
--------
**TkinterWeb provides a handful of functions that allow for manipulation of the webpage. They are fashioned after common JavaScript functions.**
How-to
--------
To manipulate the Document Object Model, use the :attr:`~tkinterweb.HtmlFrame.document` property of your :class:`~tkinterweb.HtmlFrame` or :class:`~tkinterweb.HtmlLabel` widget. For example, to create a heading with blue text inside of an element with the id "container", one can use the following:
.. code-block:: python
yourhtmlframe = tkinterweb.HtmlFrame(root, messages_enabled=True)
yourhtmlframe.load_html("
Test
")
container = yourhtmlframe.document.getElementById("container")
new_header = yourhtmlframe.document.createElement("h1")
new_header.textContent = "Hello, world!"
new_header.style.color = "blue"
container.appendChild(new_header)
.. _binding-to-an-element:
Binding to an element
---------------------
To manage bindings on HTML elements, simply use :meth:`~tkinterweb.dom.HTMLElement.bind` and :meth:`~tkinterweb.dom.HTMLElement.unbind` (new in version 4.9):
.. code-block:: python
container = yourhtmlframe.document.getElementById("container")
def callback(event):
print("Woah this is cool!")
container.bind("", callback)
-------------------
See the :doc:`api/htmldocument` for a complete list of supported commands.
See :doc:`javascript` for information on manipulating the DOM through JavaScript.
Please report bugs or request new features on the `issues page `_.
================================================
FILE: docs/source/faq.rst
================================================
Frequently Asked Questions
==========================
How do I load websites or files?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Use the :meth:`~tkinterweb.HtmlFrame.load_website` or :meth:`~tkinterweb.HtmlFrame.load_file` commands. Alternatively, use the :meth:`~tkinterweb.HtmlFrame.load_url` command to load any generic url, but keep in mind that the url must be properly formatted, because the url scheme will not be automatically applied. As always, check out the :doc:`api/htmlframe` for more information.
How do I manage clicks and use custom bindings?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* The :attr:`on_link_click` configuration option can be used to assign a custom function to link clicks. Likewise :attr:`on_form_submit` can be used to handle form submissions. See the :doc:`api/htmlframe` for more information.
* Like any other Tkinter widget, mouse and keyboard events can be bound to the :class:`~tkinterweb.HtmlFrame` widget and associated HTML elements. See the :doc:`usage` page for more information.
TkinterWeb is crashing
~~~~~~~~~~~~~~~~~~~~~~
* That is defenitely not normal. Make sure your are using the most up-to-date TkinterWeb version and have crash protection enabled.
* If you are using a :py:class:`ttk.Notebook` in your app, see the question below.
* If all else fails, `file a bug report `_. Post your operating system, Python version, and TkinterWeb version, as well as any error codes or instructions for reproducing the crash.
I'm having issues when using shrink or the HtmlLabel widget
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* See :doc:`shrink` for more information.
My app crashes when I open a tab with an HtmlFrame in it
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Tkhtml (the underlying HTML engine) and the :py:class:`ttk.Notebook` widget aren't compatable on 64-bit Windows.
* This is a known issue. Fixing this is beyond the scope of this project, but working around it is easy.
* Instead of using :py:class:`ttk.Notebook`, use :class:`tkinterweb.Notebook`. This is a wrapper around ttk.Notebook that is designed to be a drop-in replacement for the :py:class:`ttk.Notebook` widget. It should look and behave exactly like a :py:class:`ttk.Notebook` widget, but without the crashes. See `bug #19 `_ for more information.
* Please note that after adding a widget to the Notebook (eg. ``mynotebook.add(mywidget)``) there is no need to call :py:func:`~tkinterweb.Widget.pack` or :py:func:`~tkinterweb.Widget.grid` the widget. This may raise errors. TkinterWeb's Notebook widget handles all this on its own.
I get a ModuleNotFoundError after compiling my code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* When compiling your code, you might get an error popup saying ``ModuleNotFoundError: The files required to run TkinterWeb could not be found``
* Your app might also fail quietly if TkinterWeb's dependencies are not installed
* This occurs when your Python script bundler isn't finding all the files nessessary for running TkinterWeb. You need to force it to get all of TkinterWeb's files and dependencies.
* On PyInstaller: make sure you are using the latest version of PyInstaller by running ``pip install --upgrade pyinstaller pyinstaller-hooks-contrib``. Otherwise, you can also add the flags ``--collect-all tkinterweb --collect-all tkinterweb_tkhtml --collect-all tkinterweb_tkhtml_extras`` when bundling your app.
* On py2app / py2exe: Add ``'packages': ['tkinterweb', 'tkinterweb_tkhtml', 'tkinterweb_tkhtml_extras']`` to the ``OPTIONS`` variable in your setup file.
-------------------
Please report bugs or request new features on the `issues page `_.
================================================
FILE: docs/source/geometry.rst
================================================
Embedding Widgets
=================
.. note::
The API changed significantly in version 4. See :doc:`the changelog ` for details.
Overview
--------
By default, Tkinter provides three geometry managers: pack, place, and grid. While these geometry managers are very powerful, achieving certain layouts, especially with scrolling, can be very difficult.
**TkinterWeb provides a system for attaching Tkinter widgets onto the window, and handles layouts, images, selection, scrolling, and much more for you.**
How-to
------
To place a Tkinter widget inside an HTML document, add the ``data=[yourwidget]`` attribute to an ``