Hipervínculo en Tcl/Tk (tkinter)



Tk no provee por defecto la funcionalidad de enlaces o hipervínculos, tal como lo hacen otras librerías para la creación de interfaces gráficas. Sin embargo, tomando como base el control ttk.Button podemos obtener un resultado similar.

Nótese que este código utiliza el submódulo ttk, introducido en Tk 8.5, y corre en Python 3. Usuarios de Python 2 podrán ejecutar el código renombrando tkinter a Tkinter si el intérprete fue compilado junto con la versión 8.5 de Tk o una mayor.

Crearemos una nueva clase llamada Linkbutton que tendrá el mismo comportamiento que un botón convencional en Tk, pero con un nuevo estilo para conseguir la experiencia de un hipervínculo.

import tkinter as tk
from tkinter import ttk
from tkinter.font import Font, nametofont


class Linkbutton(ttk.Button):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # Obtener el nombre de la fuente por defecto.
        label_font = nametofont("TkDefaultFont").cget("family")
        self.font = Font(family=label_font, size=9)
        
        # Crear un estilo para el hipervínculo.
        style = ttk.Style()
        style.configure(
            "Link.TLabel", foreground="#357fde", font=self.font)
        
        # Aplicarlo a la clase actual.
        self.configure(style="Link.TLabel", cursor="hand2")
        
        # Configurar los eventos de entrada y salida del mouse.
        self.bind("<Enter>", self.on_mouse_enter)
        self.bind("<Leave>", self.on_mouse_leave)
    
    def on_mouse_enter(self, event):
        # Aplicar subrayado.
        self.font.configure(underline=True)
    
    def on_mouse_leave(self, event):
        # Remover subrayado.
        self.font.configure(underline=False)

Puedes cambiar el color del enlace en la línea 18 reemplazando #357fde por algún otro color de tu agrado.

El código de la ventana en la imagen anterior es el siguiente. Como verás, implementamos Linkbutton tal como lo haríamos con tkk.Button.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import ttk
from tkinter.font import Font, nametofont


class Linkbutton(ttk.Button):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # Obtener el nombre de la fuente por defecto.
        label_font = nametofont("TkDefaultFont").cget("family")
        self.font = Font(family=label_font, size=9)
        
        # Crear un estilo para el hipervínculo.
        style = ttk.Style()
        style.configure(
            "Link.TLabel", foreground="#357fde", font=self.font)
        
        # Aplicarlo a la clase actual.
        self.configure(style="Link.TLabel", cursor="hand2")
        
        # Configurar los eventos de entrada y salida del mouse.
        self.bind("<Enter>", self.on_mouse_enter)
        self.bind("<Leave>", self.on_mouse_leave)
    
    def on_mouse_enter(self, event):
        # Aplicar subrayado.
        self.font.configure(underline=True)
    
    def on_mouse_leave(self, event):
        # Remover subrayado.
        self.font.configure(underline=False)


class Application(ttk.Frame):
    
    def __init__(self, main_window):
        super().__init__(main_window)
        main_window.title("Hipervínculo en tkinter")
        self.create_widgets()
    
    def create_widgets(self):
        self.link = Linkbutton(self,
            text="Clic en el hipervínculo", command=self.link_clicked)
        self.link.place(x=40, y=70)
        self.place(width=300, height=200)
    
    def link_clicked(self):
        print("Clicked!")


main_window = tk.Tk()
app = Application(main_window)
app.mainloop()

El hipervínculo puede realizar cualquier acción al momento de ser presionado. Si quieres que abra la dirección de una página web, el módulo estándar webbrowser te permite hacerlo:

    def link_clicked(self):
        import webbrowser
        webbrowser.open("recursospython.com")



2 comentarios.

  1. Hola, acabo de conocer esta página. ¿Hay alguna manera de suscribirse? …. Qizas a través de “newsletters”??

    Sobre este tema de los enlaces web… Si, hay otra manera de hacer hiper-enlaces, y segun mis comprobaciones es más rápido (cuando hay muchos).
    Pongo un ejemplo tomado de effbot.org, consta de una clase y del programa de llamada (no pongo mi adaptación, porque es demasiado codigo):

    Nota: espero que no moleste.

    # clase_hipervinculos.py
    from tkinter import *

    class GestorHyperlinks:

    def __init__(self, text):

    self.text = text

    self.text.tag_config(“hyper”, foreground=”blue”, underline=0)

    self.text.tag_bind(“hyper”, “”, self._enter)
    self.text.tag_bind(“hyper”, “”, self._leave)
    self.text.tag_bind(“hyper”, “”, self._click)

    self.reset()

    def reset(self):
    self.links = {}

    def add(self, action):
    # add an action to the manager. returns tags to use in
    # associated text widget
    tag = “hyper-%d” % len(self.links)
    self.links[tag] = action
    return “hyper”, tag

    def _enter(self, event):
    self.text.config(cursor=”hand2″)

    def _leave(self, event):
    self.text.config(cursor=””)

    def _click(self, event):
    for tag in self.text.tag_names(CURRENT):
    if tag[:6] == “hyper-“:
    self.links[tag]()
    return

    —————–

    #prueba_hiper.py
    import clase_hipervinculos as hiper

    from tkinter import *

    root = Tk()
    root.title(“hyperlink-1”)

    text = Text(root)
    text.pack()

    hyperlink = hiper.GestorHyperlinks(text)

    def click1(a,b,c):
    print (“click 1”, a, b, c)

    text.insert(INSERT, “this is a “)
    text.insert(INSERT, “Qd2”, hyperlink.add(lambda:click1(1,2,3)))
    text.insert(INSERT, “\n\n”)

    def click2():
    print (“click 2”)

    text.insert(INSERT, “este es otro enlace “)
    text.insert(INSERT, “enlace”, hyperlink.add(click2))
    text.insert(INSERT, “\n\n”)

    mainloop()

    • Recursos Python says:

      Hola, sí, podés suscribirte a nuestra newsletter. Agradezco tu aporte, de todas formas no es exactamente lo mismo. El código que se provee en este artículo es para un hipervínculo que funcione como un widget en sí mismo (similar a un botón), mientras que tu ejemplo permite incluir enlaces dentro de cajas de texto.

      Saludos

Deja un comentario