Getting Started

Note

The API changed significantly in version 4. See the changelog for details.

Installation

To use TkinterWeb, first install it using pip:

$ pip install tkinterweb[recommended]

Tip

You can also choose from the following extras:

$ pip install tkinterweb[html,images,svg,javascript,requests]

Run pip install tkinterweb[full] to install all optional dependencies or pip install tkinterweb to install the bare minimum.

Run the TkinterWeb demo to see if it worked!

>>> from tkinterweb import Demo
>>> Demo()
_images/tkinterweb-demo.png

TkinterWeb requires Tkinter, TkinterWeb-Tkhtml, PIL, and PIL.ImageTk. All dependencies should be installed when installing TkinterWeb the recomended way, but on some systems PIL.ImageTk may need to be installed seperately in order to load most image types.

Getting started

TkinterWeb is very easy to use! Here is an example:

import tkinter as tk
from tkinterweb import HtmlFrame # import the HtmlFrame widget

root = tk.Tk() # create the Tkinter window

yourhtmlframe = HtmlFrame(root, messages_enabled=True) # create the HtmlFrame widget
yourhtmlframe.load_html("<h1>Hello, World!</h1>") # load some HTML code
yourhtmlframe.pack(fill="both", expand=True) # attach the HtmlFrame widget to the window

root.mainloop()

You can also use load_website(), load_file(), or load_url() to load webpages.

The HtmlFrame widget behaves like any other Tkinter widget and supports bindings. It also supports link clicks, form submittions, website title changes, and much, much more! See below for more tips and tricks.

Tip

Use the HtmlLabel widget for an HTML-based label widget and the HtmlText widget for an HTML-based text widget.

Tips and tricks

Creating bindings

Like any other Tkinter widget, mouse and keyboard events can be bound to the HtmlFrame widget.

The following is an example of the usage of bingings to show a menu:

def on_right_click(event):
    # Get the element under the mouse and its url
    element = yourhtmlframe.get_currently_hovered_element()
    url = element.getAttribute("href")

    if url:
        # Resolve the url to ensure it is a full url
        url = yourhtmlframe.resolve_url(url)

        # Create the menu and add a button with the url
        menu = tk.Menu(root, tearoff=0)
        menu.add_command(label="Open %s" % url,
            command=lambda url=url: yourhtmlframe.load_url(url))

        # Show the menu
        menu.tk_popup(event.x_root, event.y_root, 0)

yourhtmlframe.bind("<Button-3>", on_right_click)

This will make a popup open when the user right-clicks on a link. Clicking the link shown in the popup would load the website.

Note that some keypress events are automatically bound to the widget. If you notice a feature unintentionally stops working after adding a binding, consider using bind(event, callback, add="+") to add your binding instead of replacing the default one.

Tip

Since version 4.10, you can also bind to a specific HTML element! See Binding to an element for more details.

Changing the title

To change the title of the window every time the title of a website changes, use the following:

def change_title(event):
    root.title(yourhtmlframe.title) # change the title

yourhtmlframe.bind("<<TitleChanged>>", change_title)

Similarily, the <<IconChanged>> event fires when the website’s icon changes.

Handling url changes

Normally, a website’s url may change when it is loaded. For example, “https://github.com” will redirect to “https://www.github.com”. This can be handled with a binding to <<UrlChanged>>:

def url_changed(event):
    updated_url = yourhtmlframe.current_url
    ### Do stuff, such as change the content of an address bar

yourhtmlframe.bind("<<UrlChanged>>", url_changed)

This is highly recomended if your app includes an address bar. This event will fire on page redirects and url changes when a page stops loading.

Searching the page

Use find_text() to search the page for specific text. To search the document for the word ‘python’, for example, the following can be used:

number_of_matches = yourhtmlframe.find_text("python")

Or, to select the second match found:

number_of_matches = yourhtmlframe.find_text("python", 2)

Refer to the API reference for more information.

Tip

Check out bug 18 or the sample web browser for a sample find bar!

Done loading?

Website loading is performed asynchronously. When loading a website, you can bind to the <<DoneLoading>> event, which fires when the document has finished loading.

If you bind to <<DoneLoading>> to update GUI state (for example, switching a ‘Stop’ button to ‘Refresh’), it is generally recommended to also bind to the <<DownloadingResource>> event to handle the opposite case. Without this, the document may report that it has finished loading while additional resources (such as images, scripts, or stylesheets) are still being downloaded.

When loading raw HTML or local files, the page loads synchronously and can be manipulated immediately.

Stop loading

The method stop() can be used to stop loading a webpage. If load_url(), load_website(), or load_file() was used to load the document, passing yourhtmlframe.current_url with force=True will force a page refresh.

Zooming

Setting the zoom of the HtmlFrame widget is very easy. This can be used to improve accessibility in your application. To set the zoom to 2x magnification the following can be used:

yourhtmlframe = HtmlFrame(master, zoom=2)
### Or yourhtmlframe.configure(zoom=2)
### Or yourhtmlframe["zoom"] = 2

To scale only the text, use fontscale=2 instead.

Embedding a widget

There are many ways to embed widgets in an HtmlFrame widget. One way is to use <object> elements:

yourcanvas = tkinter.Canvas(yourhtmlframe)
yourhtmlframe.load_html(f"<p>This is a canvas!</p><object data="{yourcanvas}"></object>")

Refer to Embedding Widgets for more information.

Manipulating the DOM

Refer to Manipulating the Page (new in version 3.25).

Using JavaScript

Refer to Using JavaScript (new in version 4.1).

Making the page editable

Refer to Making Documents Editable (new in version 4.8).

Shrinking a widget to match its contents

Refer to Creating a Label Widget.

Using dark mode

You can set dark_theme_enabled=True when creating your HtmlFrame or calling configure() to turn on dark mode and automatically modify page colours.

If you set image_inversion_enabled=True, an algorithm will attempt to detect and invert images with a predominantly light-coloured background. This helps make light-coloured images or pictures with a white background darker.

Refresh the page for these features to take full effect. This features may cause hangs or crashes on more complex websites.


See the HTML Widgets Documentation for a complete list of available commands.