Topic: Tooltip in tkinter  (Letto 319 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 274
  • Punti reputazione: 0
    • Mostra profilo
Tooltip in tkinter
« il: Gennaio 06, 2020, 13:26 »
Saluti a Voi :)

Il presente post NON È una richiesta di supporto ma una "offerta" che porgo agli utenti che stanno iniziando con python e che, come constato, si avventurano a programmare GUI con tkinter.

Avendo deciso di fare, solo per sperimentare alcuni pattern (MVC-Observer), quello che sarà il mio ultimo "esperimento" con tkinter, poi passerò ad altro framework, organizzandolo "come piace a me", ossia con tutti gli "accorgimenti" che mi piace realizzare in una finestra grafica, Uno dei detti "accorgimenti" e applicare "tooltip", tanto ai vari widget, quanto ai menu, cosa che in tkinter non è possibile fare a meno di non integrare nel proprio codice l'obsoleta libreria TIX ed utilizzare il controllo aggiuntivo "balloon" ... cosa che non ho voluto fare.

Con l'aiuto di San Google e di un paio di classi, in parte personalizzate, trovare su stackoverflow, citata la fonte nella docs delle calssi che seguono, ho realizzato un sistema di tooltip utilizzabili in tkinter senza aggiungere ulteriori librerie, articolato in tre classi.

La prima "CreaToolTip" è dedicata ai widget "comuni" e si invoca chiamando "tooltip = CreaToolTip(widget, testo)", ovvio che è solo uno schema di chiamata, ove "widget" è il controllo cui deve essere applicato il tootip e "testo" è il testo da applicarsi, va da se che un toltip definito in una classe deve essere memorizzato quale variabile di istanza della classe stessa.

Le altre due classi sono dedicare a far apparire dei tooltip in un menu tkinter, applicati ai soli item "command", ed è ottenuta sub-classando la classe "Menu" di tkinter nella classe "MenuTooltip" che provvede a memorizzare indice e tooltip di un item "command" definito, quindi ad intercettare il passaggio del mouse esponendo il tooltip corrispondente all'item sottostante il puntatore. La definizione del tooltip avviene semplicemente aggiungendo un ulteriore argomento "tooltip=testo_da_mostrare" in una invocazione "menu.add_command()". Poi provvede la classe "MenuTooltip ad invocare la classe "ToolTipWin" che provvede a visalizzare effettivamente il tooltip.
Preciso che dette classi sono limitate a ciò che ritengo mi serva per lo studio per cui sono state create, potrebbero facilmente essere ridotte a due le classi necessarie ed espanse le tipologie di item servite, compito degli eventuali interessati, se vogliono.

In successione a questo post ne farò un altro per fornirvi un esempio funzionale di test, sarebbe troppo lungo per un unico post dato che una interfaccia che stavo preparando per miei scopi e durante la cui realizzazione mi è venuto il pensiero che questo argomento potrebbe interessare altri utenti del Forum.

Intanto, il codice delle classi definenti i tooltip, 202 righe ;
# -*- coding: utf-8 -*-

import tkinter as tk

# *** CLASSI DI UTILITÀ DERIVATE DA ALTRE TROVATE IN GIRO ED ADATTATE ***

class CreaToolTip(object):
    '''
Crea un tooltip per un generico widget.

Esempio originale tratto da stackoverflow, indirizzo:
https://stackoverflow.com/questions/3221956/how-do-i-display-tooltips-in-tkinter

eseguite minime personalizzazioni.
'''
    def __init__(self, controllo, msg=''):
        self.attesa = 500                # Tempo di attesa in millisecondi
        self.lunghezza = 300             # dimensione del messaggio in pixel
        self.controllo = controllo
        self.testo = msg
        # Utilizza gli eventi del controllo chiamante
        self.controllo.bind('<Enter>', self.avvia)
        self.controllo.bind('<Leave>', self.chiudi)
        self.controllo.bind('<ButtonPress>', self.chiudi)
        self.id = None
        self.tw = None

    def avvia(self, event=None):
        self.schedule()

    def chiudi(self, event=None):
        self.unschedule()
        self.nasconditip()

    def schedule(self):
        self.unschedule()
        self.id = self.controllo.after(self.attesa, self.mostratip)

    def unschedule(self):
        iden = self.id
        self.id = None
        if iden:
            self.controllo.after_cancel(iden)

    def mostratip(self, event=None):
        x = y = 0
        x, y, cx, cy = self.controllo.bbox('insert')
        x += self.controllo.winfo_rootx() + 25
        y += self.controllo.winfo_rooty() + 20
        # crea una finestra toplevel con padre il controllo
        self.tw = tk.Toplevel(self.controllo)
        # lascia solo la label e rimuove gli elementi della finestra
        self.tw.wm_overrideredirect(True)
        self.tw.wm_geometry('+%d+%d' % (x, y))
        messaggio = tk.Label(self.tw,
                             text=self.testo,
                             justify='left',
                             background='#f6f6e3',
                             relief='solid',
                             borderwidth=1,
                             wraplength=self.lunghezza
                             )
        messaggio.pack(ipadx=1)

    def nasconditip(self):
        tw = self.tw
        self.tw = None
        if tw:
            tw.destroy()



class MenuTooltip(tk.Menu):
    '''
    da https://stackoverflow.com/questions/55316791/how-can-i-add-a-tooltip-to-menu-item
    permette di aggiungere un tooltip ai menu-items.
    Introdotte variazioni funzionali rispetto all'esempio citato.
    '''
    def __init__(self, parent):
        """
        :parametro parent: il master del Menu, può essere 'root' o 'Menubar'
         .tooltip == Lista di tuple (yposition, text)
         .tooltip_active == Indice (0-based) del Tooltip attivo
         eventi intercettati <Leave>, <Motion>
        """
        super().__init__(parent, tearoff=0)
        self.tooltip = []
        self.tooltip_active = None
        self.tooltip_win = None

        self.bind('<Leave>', self.leave)
        self.bind('<Motion>', self.on_motion)

    def add_command(self, *cnf, **kwargs):
        tooltip = kwargs.get('tooltip')
        if tooltip:
            del kwargs['tooltip']
        super().add_command(*cnf, **kwargs)
        # chiede l'indice dell'ultimo command
        u_command = self.index("end")
        self.add_tooltip(u_command, tooltip)

    def add_tooltip(self, index, tooltip):
        """
        :parametro index  : Indice (0-based) degli item del Menu
        :parametro tooltip: Testo da mostrare quale Tooltip
        :return: None
        """
        self.tooltip.append((self.yposition(index) + 2, tooltip))

    def on_motion(self, event):
        """
        Cicla i .tooltip per trovare il Menu Item
        """
        for idx in range(len(self.tooltip) - 1, -1, -1):
            if event.y >= self.tooltip[idx][0]:
                x = event.x_root
                y = event.y_root
                point = (x, y)
                self.show_tooltip(idx, point)
                break

    def leave(self, event):
        """
        Distrugge il Tooltip corrente e resetta .tooltip_active a None
        """
        if not self.tooltip_active is None:
            # destroy(<tooltip_active>)
            if self.tooltip_win:
                self.tooltip_win.chiudi()
            self.tooltip_active = None

    def show_tooltip(self, idx, point):
        """
        Mostra il Tooltip se non presente, distrugge il Tooltip attivo
        :parametro idx: Indice del Tooltip mostrato
        :point        : coordinate di posizionamento del tooltip
        :return: None
        """
        if self.tooltip_active != idx:
            # destroy(<tooltip_active>)
            if self.tooltip_win:
                self.tooltip_win.chiudi()
            # create new tooltip
            self.tooltip_active = idx
            msg = self.tooltip[idx][1]
            self.tooltip_win = ToolTipWin(self, point, msg)
            self.tooltip_win.avvia()


# *** MIE CLASSI ***

class ToolTipWin(object):
    '''
Ricodifica della classe CreaToolTip mirata alla esposizione di tooltip
in un menu tkinter (gli oggetti items non vengono restituiti quali widget)
'''
    def __init__(self, ctrl, point, msg=''):
        self.attesa = 500
        self.lunghezza = 300
        self.ctrl = ctrl
        self.text = msg
        self.point = point
        self.id = None
        self.tw = None

    def avvia(self):
        self.unschedule()
        self.id = self.ctrl.after(self.attesa, self.mostra_tip)

    def chiudi(self):
        self.unschedule()
        self.nascondi_tip()

    def unschedule(self):
        iden = self.id
        self.id = None
        if iden:
            self.ctrl.after_cancel(iden)

    def mostra_tip(self):
        x, y = self.point
        # crea una finestra toplevel con padre il menu
        self.tw = tk.Toplevel(self.ctrl)
        # lascia solo la label e rimuove gli elementi della finestra
        self.tw.wm_overrideredirect(True)
        self.tw.wm_geometry('+%d+%d' % (x, y))
        messaggio = tk.Label(self.tw,
                            text=self.text,
                            justify='left',
                            background='#f6f6e3',
                            relief='solid',
                            borderwidth=1,
                            wraplength=self.lunghezza
                            )
        messaggio.pack(ipadx=1)

    def nascondi_tip(self):
        tw = self.tw
        self.tw = None
        if tw:
            tw.destroy()

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 274
  • Punti reputazione: 0
    • Mostra profilo
Re:Tooltip in tkinter
« Risposta #1 il: Gennaio 06, 2020, 13:35 »
Ora il codice di test ed esempio, questo test importa "my_tk_object" che altri non è che il codice esposto prima, più "risorse" che è un file python in cui serializzo immagini per icone e testi associati, oltre ad un oggetto che provvede a restituirli, segue il codice relativo, ed inoltre una tabella di riempimento che è stata già postata qui (import tbl_orig) , copiatevela se volete vedere l'esempio funzionale.

il codice di test, 161 roghe
#-*- coding: utf-8 -*-

import tkinter as tk
import risorse as res
import my_tk_object as mtko
from my_tk_object import CreaToolTip as ctt
import tbl_orig as tbl


class GUIAnag(tk.Tk):
    '''Window di test/esempio per utilizzo di tooltip in tkinter'''
    def __init__(self):
        super().__init__()
        self.title('Anagrafiche')
        ids = res.IcoDispencer()
        # --- IMMAGINI PER MENU ---
        self.img_anag = tk.PhotoImage(data=ids.getIco('anagrafiche'))
        self.img_nuova = tk.PhotoImage(data=ids.getIco('nuova'))
        self.img_modifica = tk.PhotoImage(data=ids.getIco('modifica'))
        self.img_salva = tk.PhotoImage(data=ids.getIco('salva'))
        self.img_annulla = tk.PhotoImage(data=ids.getIco('annulla'))
        self.img_cancella = tk.PhotoImage(data=ids.getIco('cancella'))
        self.img_cerca = tk.PhotoImage(data=ids.getIco('cerca'))
        self.img_esci = tk.PhotoImage(data=ids.getIco('chiudi'))
        # --- MENU ---
        barra_menu = tk.Menu(self)
        self.config(menu=barra_menu)
        self.m_anag = mtko.MenuTooltip(barra_menu)
        barra_menu.add_cascade(label='Anagrafiche',
                               menu=self.m_anag,
                               compound='left',
                               image=self.img_anag
        )
        self.m_anag.add_command(label='Nuova',
                                compound='left',
                                image=self.img_nuova,
                                tooltip=ids.getDescr('nuova')
        )
        self.m_anag.add_separator()
        self.m_anag.add_command(label='Modifica',
                                compound='left',
                                image=self.img_modifica,
                                tooltip=ids.getDescr('modifica')
        )
        self.m_anag.add_separator()
        self.m_anag.add_command(label='Salva',
                                compound='left',
                                image=self.img_salva,
                                tooltip=ids.getDescr('salva')
        )
        self.m_anag.add_command(label='Annulla',
                                compound='left',
                                image=self.img_annulla,
                                tooltip=ids.getDescr('annulla')
        )
        self.m_anag.add_separator()
        self.m_anag.add_command(label='Cancella',
                                compound='left',
                                image=self.img_cancella,
                                tooltip=ids.getDescr('cancella')
        )
        self.m_anag.add_command(label='Cerca',
                                compound='left',
                                image=self.img_cerca,
                                tooltip=ids.getDescr('cerca')
        )
        self.m_anag.add_separator()
        self.m_anag.add_command(label='Esci',
                                compound='left',
                                image=self.img_esci,
                                tooltip=ids.getDescr('chiudi'),
                                command=self.destroy
        )
        # --- PANNELLO FOTO ---
        p_foto = tk.Frame(self, padx=4, pady=4)
        p_foto.grid(row=0, column=0, sticky='nsew')
        self.c_foto = tk.Canvas(p_foto,
                                bg='#ffffc0',
                                width=100,
                                height=100,
                                relief='raised',
                                border=2
                                )
        self.c_foto.grid(row=0, column=0)
        p_foto.grid_columnconfigure(0, minsize=10, weight=1)
        p_foto.grid_rowconfigure(0, minsize=10, weight=1)
        # --- PANNELLO DATI ---
        p_data = tk.Frame(self, padx=4, pady=4)
        p_data.grid(row=0, column=1, sticky='ew')
        lbl1 = tk.Label(p_data, text='Codice', padx=2)
        lbl1.grid(row=0, column=0, sticky='ew')
        self.e_ID = tk.Entry(p_data, width=6)
        self.e_ID.grid(row=0, column=1, sticky='ew')
        self.ck_persona = tk.Checkbutton(p_data, text='Persona fisica', padx=2)
        self.ck_persona.grid(row=0, column=2, sticky='ew')
        ttp = 'Spunta definisce definisce Persona fisica, giuridica altrimenti'
        self.ck_persona_ttp = ctt(self.ck_persona, ttp)
        self.ck_obsoleto = tk.Checkbutton(p_data, text='Obsoleto', padx=2)
        self.ck_obsoleto.grid(row=0, column=3, sticky='ew')
        ttp = 'Spunta definisce dato obsoleto e non modificabile'
        self.ck_obsoleto_ttp = ctt(self.ck_obsoleto, ttp)
        lbl2 = tk.Label(p_data,
                        text='Cognome/Rag. Sociale :',
                        anchor='w',
                        padx=2
                        )
        lbl2.grid(row=1, column=0, columnspan=4, sticky='ew')
        self.e_cognome = tk.Entry(p_data)
        self.e_cognome.grid(row=2, column=0, columnspan=4, sticky='ew')
        ttp = 'Cognome o ragione sociale del soggetto'
        self.e_cognome_ttp = ctt(self.e_cognome, ttp)
        lbl3 = tk.Label(p_data, text='Nome :', anchor='w', padx=2)
        lbl3.grid(row=3, column=0, columnspan=2, sticky='ew')
        lbl4 = tk.Label(p_data, text='Nato il :', anchor='w', padx=2)
        lbl4.grid(row=3, column=2, columnspan=2, sticky='ew')
        self.e_nome = tk.Entry(p_data)
        self.e_nome.grid(row=4, column=0, columnspan=2, sticky='ew')
        ttp = 'Nome del soggetto (se persona fisica)'
        self.e_nome_ttp = ctt(self.e_nome, ttp)
        self.e_nato = tk.Entry(p_data)
        self.e_nato.grid(row=4, column=2, columnspan=2, sticky='ew')
        ttp = 'Data di nascita, formato dd/mm/aaaa (se persona fisica)'
        self.e_nato_ttp = ctt(self.e_nato, ttp)
        lbl5 = tk.Label(p_data, text='Luogo di nascita :', anchor='w', padx=2)
        lbl5.grid(row=5, column=0, columnspan=2, sticky='ew')
        lbl6 = tk.Label(p_data, text='Cod. Fisc./P.ta IVA :', anchor='w', padx=2)
        lbl6.grid(row=5, column=2, columnspan=2, sticky='ew')
        self.e_loc = tk.Entry(p_data)
        self.e_loc.grid(row=6, column=0, columnspan=2, sticky='ew')
        ttp = 'Comune o stato estero di nascita'
        self.e_loc_ttp = ctt(self.e_loc, ttp)
        self.e_cf = tk.Entry(p_data)
        self.e_cf.grid(row=6, column=2, columnspan=2, sticky='ew')
        ttp = 'Codice fiscale o partita IVA del soggetto'
        self.e_cf_ttp = ctt(self.e_cf, ttp)       
        p_data.grid_columnconfigure(0, weight=1)
        p_data.grid_columnconfigure(1, weight=1)
        p_data.grid_columnconfigure(2, weight=1)
        p_data.grid_columnconfigure(3, weight=1)
        self.grid_columnconfigure(1, weight=1)
        g = {'minsizes' : [0, 0, 0],
             'weights'  : [1, 1, 1]
             }
        h = ['Cognome', 'Nome', 'data nascita']
        data = [['De Paperoni', 'Paperon', '1901-01-01'],
                ['Paperino', 'Paolino', '1950-11-01'],
                ['Paperone', 'Gastone', '1950-01-06'],
                ['Mouse', 'Miky', '1900-02-29'],
                ['Mouse', 'Minnie', '1910-01-01'],
                ['Mucca', 'Clarabella', '1923-12-13']
                ]
        model = tbl.TableModel(g, h, data)
        tabella = tbl.Table(self, model)
        tabella.grid(row=1, column=0, columnspan=2, sticky='nsew')



if __name__ == '__main__':
    root = GUIAnag()
    root.mainloop()

Il file "risorse.py" sono altre 290 righe :( ... separo il post

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 274
  • Punti reputazione: 0
    • Mostra profilo
Re:Tooltip in tkinter
« Risposta #2 il: Gennaio 06, 2020, 13:37 »
infine, per completare l'esempio, risorse.py, 290 righe, la tabella, se vi serve (ammesso l'argomento interessi qualcuno), copiatela dal post prima lincato
# -*- coding: utf-8 -*-

icoanagrafiche = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAD8klEQVR42mIYGcDPVIIp0pA3KdhEYo6
XgXiNu66YIFUM9rAUmZpszfM/yVzwf4SN4n9fQ4mLUbZKrAQ1ziiPsZ1dFb9xXX/ZsZ1zWpt2zG7mhM
l5motxe1oL/WzNdQUUSw9AriQBGIBztm2jeLZt27ZtrW0rl7XtDZZxVtFk4mQ2th//m+xZuSu+rmp3f
01IevIhn2Li2ZvOxQMXH3/df6FXV3/29Namb1/GdGMmxAM1mKj9YXiClbXZ/83rt56W/9kD8MvHELWu
0nEF08x0vH7X+Q+lhKs+fapX1F2EKWYOhqq+x2JXOXoLP0LDVy+ck+wnOMwTyKnKHSGCjbhdhRi1Cpe
0F/z2zDtSwn2F7wv862OIGMWIUuuIWlagmmah9vNnbkj2S6W1DM8SsymgoMcY+AiRs7DM1ifmf/zy3+
9YM9Ow+2p/oTWgmKRhCWJJmD6uZ20Cgta0l34d5+ZWnOIWtuwMrA/Bv9yD4o/uiN51+YG7pdyxmVvHD
qyP0rAQMYsMUZME/vXRhHK4+Ixfx7gWGxnkSH6M4laDHC3Cu/eese3Ry/fbNyXsXGg42ydp3x5WTyOq
nUWYYMMn625J9nE4nOPX2W23uRdqs72yXtj5rfDQ9/vRnSejO/2p93hc7k1c9vTe/4rb5uoGaByBlV6
4ha2QDRTf4OKVv+m06hJOQgAPnwWvpBNeaTccNP7B1Qeg7dunEYlEsLHUSjjZRUf+I7w20/ataqIKyp
ESiAfKQfJazvUIWHGXVQcnKYZP2gUvvaCPxte70vD+5fvhm3vPQTweh03UA/diw+f/CPuMKzXEQj8mm
dkg+YNwSAYKPMIWOMwkHLoVJMseUTK2oj/jWbx62cF46ZKDsGHSgRJ0ws1nLv6GqTQb+5N6x/Nmq2fe
ZnPtJGVzEIy3w0ysIRyKIGAlQJkMMKlXYF9kwSVsg1PQhumy91D65u0YqPoBNpsNWi5rp5HdOLWJsuc
UN2h0dofbE0I4Ekc0lkA0mkCEjtHYFsTiWzbzYCgGt9sPiWRFLxSIk5ES8EUG/qJoeXFBNMCZmf+67I
eMC6+46KPdGdJV0x5rCrPe5vBvojT2rzEYpmFvCC5PsOiEw5/c/fSTXtrjhMOe3v3QAx/8+x8WyXQ3a
XQ2UDYvQuF4yhgIRmF3BkBvwmoyenZnpAqceUWa3uSEweSC1x9GIBT715jcLWXz0dG7fXndeEZKOL9q
fL+OAf7zS2JNp1JDqejd+wmdLaHSUNvkast2BWHdSrfHlARlX5GbBAtCoqShlXdFSekQ43+FR9LSGBW
N3N2qmtj7FtdOHl5YM3FMUe3EcYXVE0eV1U8fVMlk71lSPsnY5eEnEecbPy8tyA8AAAAASUVORK5CYI
I=
'''

icoannulla = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAEHklEQVR42mJITk5mYmBgEARiUQqxUEJ
CAhMDEpD7TyUA4KMcgBzLojCcwtrFKaxt27Zt27Z3p23bSnpsxOm0bWPVjB6Dzr/nnTHSt+q/yqsvF1
9dYp22N/h0ADD3u2ChmPrmYRv0cF9rrYNuWPu1uGAdcGtjjo362jfmvgUYu+d2gc85APxnRiUqNzfCM
ehCjn4rYjIr8O3yNGRVbkJ8nh45NVsQn6tHStFqLM8oR1RmGWrNnagbZHhksJlWurn9b/7IwquYxbbO
adiHfNhOfW3O1DPH87ZBL3ilPbvmlwCLPi9EwQPB54Ys+qBI4j7xyxL8igRVFhBQZI42DqoK/S5EBhc
UFKCxsRE+nw9lZWXYvGUL9Ho9Vq5cCbvdwb+vW7cODocDefn50BsMPM7OzkZ3d3dksM/jwtzMNK9clU
UIXg+m//mb2/m5aWrdEOgbUfDyjnaFxjTvjgy20C2zBf0uPlftHG1De2If9vG8Y1hA3YgIx4jA/R0GL
QH+KaEAebVG1I94EZdbjcT8WnwflYHSdXVILlyBBDIjz7CNjChFFFnxZ3opforPQeOYQItZcsUeuv2Z
nf56YeyaYQu0mHvnKXPkroctsA6Q72SHieYt/drYExksiwKfrSwJCKgyggEVQb+KUEDhccDPc1gMqgi
HAgCFBtxfDPkjg0tKSrB9+3ZIksRWGI1G5ObmYv369VAUheP3+xEIBBAMhRAGF+4Hg0HuaywNuHJvMH
nKPqqSSCtV2F0fmeBXJYqMxZ0rpIoh7Z+8h87vvsbeJUqnW+O49bq1+6zYOuCFVbOC7Nh1+84xGc5RC
XVaf1RAw7iC5hlg4113wPvjV5j77RuseuMDNAtA87tvhF2/fAMh5nesPWlZ9W7wF7+nonyDk61IL1uP
5OKV+OCb35FasgrRWeWo2tKMH2Ky8HNKETJvuw2jbzyGnseeQP/nb2L5Jedh8OPX0fPoE5j47gOUHXX
oz3tWTCawFQMuaqf57bCTv+yztotBD/nMO4JtKoCaF95A15M3wXH5Veh9+Sm0PPgY+j9+Blk63R+6/c
6Yz1NVJLpwlcO3j0XsW8J83lqpvOFiNF9xJrYdfwKcFyxD2vGH12tA/d7glJQUNDQ08O3X1NTwu0FG8
FthMBjgdDpht9tRVV2Npq4ulD33JHqvORUtOh0GL+UWfXdciOijj4jf12NZhsvlgiiKUFWV+/QnPE8K
ctxuN4LhMNZ89hH+vu4C/EewpntuxGM3XxvuvON6TNN48p6bkXPlFbEM1vxcWFjgEHD/MHBXXIKAnMc
fgnLZRRh/+F48eOmloZ+WLxdvPfWUhX/vvR3eG69B5v/T11nMoK+vzw403AyIrYnGXJyWveYGO+OFBC
awCglZCAoKGjNoagpXKylMXmFlsQzkWgAF/hUIGnXFJgAAAABJRU5ErkJggg==
'''

icocancella = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAADxklEQVR42rXUA5AcaRTA8WvdzMW2k7U
R25nYtu2kcNbclWLbtr3G7GRvrc7Yax7n6373umondrKv6j9+v3F/AQBV0kct4TTbvGDe44WTJ+crFA
oTx3FbPhnGabI2NDg8d+N6oSQ2Rji6Y4ewcOHCIsT34n3UR8E4jVcFB4RZFs4V7LOmQe7PP0JFQYFw7
NgxYcWKFRJ+GB9DfxCM02hlgN9Dw6xpgmnyBLBsXAcFNqtYXFwMpaWl5OjRo8LatWuLZDLZSemVvy/a
YImX533NpPGCbvRIMK5eCXkWi5hvs0FRURFIeJnVSo7t3CnMnj3bho/n3getv9Dd/V72qBECrxgM2qW
LwWEyiTm3boF682awa7VgT0sldsUAKLp9k3yzalXRO2GcevPat7+dohgsZPTrC9nz5oFNrxezbt4EXU
wMGNRqsCYnEXPnIDC2aQa6TkHku6FDwqXP+W1onVlt2tz6o28fIblrV0ifPh0sOp2oTUiA1DNn4ElEB
JgSHxNdoC9omtSDbLc2ZCxLXZb2pP03ojNatbqh6tZVUAcHQ9LEiWDSaESzRgNply+DhBvUCYT39YCs
ejUhqbqMjGKeoVKvQ2tNbdbselxICEnw84OksWPByPOi1WqFsPXrgY+OBp1KRTI6tIXU6jJQcTQZTlF
XnqKvg3FqTm7U6EqMjw+Jd3ODxOHDQZ+dLaZevQqqnTvhiUoFmthYZ0rr5pDIURCN6FCauvoUfR2MU2
NMw4aXotzcSGyrVqAeOBB0mZliFn6W6oMHwcDzkBMV5VQ3bQwqloZHHEMG0+xT9I1wjx49+k1VKEp3N
Gz4r6pPH9Ckp4sGvR6ilErIwVeaHRnpjGvSGGIYGu6yDBlEs9fehD6Fu3fvPvDAgQPleXl58OPateLl
Q4eIHlFXmeHhzmhEIxC9wbKkP81dfxsqJU3b3bt3FxQWFoIE22w2+PVXpXjx4sX/JDQjLMwZ2aQJhDE
MXGM50vc9UBdM+fv7H+R5/m+HwwF2ux0sFgsof/tdPL1161P0KqJ9aO7G+6BSLp3y8/M7mJmZ+beEms
1mMBgM8O3yFaJSJv/3ioSyspvviz6FMdcrP5CWlva30WgECdbpdDCgU2dHN/bLe3h/G6wGJsPo94IrF
1pjQd7e3meSkpL+1mq1sGzZMptcLu8k3f+Wz5LCWEwu5Xrip8darAs2Hlvu5uYWNnfuXBseuBfh9QFY
H6wH1hkLwfwxPyywMi+sDdYEq+mCn4bzFdYYc8d6VmL9scGYAutXiftgbbGmWF2sOsZhlMv6H9EsWMP
XC538AAAAAElFTkSuQmCC
'''

icocerca = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAD7klEQVR42qXUU4BjZwMG4NXV/19Va9v
escu1bdu2bds7tm1bsZNJJrbRvj1J7Ta5eI/P8/nrAOBvk3TvSMfcF2e7Oq//S/4O/H/hmwt5qQ+P29
OfnEZJxG1bdfyD+Kzn5zt5BOc8P0tJfXwKRAEoibqL1vwY0MtTUZvyvNRtuODNhQXxdw4h88U5JNw9h
uw3V1Cf8Q6Ukng0ZL5HwdvLPd2CSz5c/dCS+Qw6RhH0glYwq7MgaCqEmFqOoog7KAu/stktuDz6Vqqs
IREGTiXMYioschasSh5x5oDfkIu6hLuH3ILp+W+fa0jpMPBqYJbQCJANq0oAi4ILHb8JzMJ3N9yCBVX
xNzXkH2EpActYsLhqzCYKoti5pVHT3IL5ZZE91c2pJAOnAhYJGRYpHVYZgzjToOfXZXs03cTV0Tf19F
yY+JWwiBqINLrS3pBxwDO44t3HgqooGBgFMHLKYeJVglkeh7bSD//zCHaGVBxjFNcRs4OeD0FVLBrzI
lTO5x7Dan6zQc6uR3Xaa9RlfYCIUib3GBaLxJuMSiF0QgpaCmPRnB+NNkYTqsvLH9jtjp/3i4ULF3bO
TM9cWnjmTJe/hJVK9Sdisfa0SKIWaHUmiCSqb9tFEjBJjWBQqdi/bx8mT5wMrdYgMJlsp202R/dpU6e
WjBs3DkcOHmr+U5jFkV4UtmvsOgI0Gi0wm21ErLBa7SC1krB9y1bMnj0bc2bNxorlKxEcHIYL5698Fx
Ic7Jg3Zw4O7NuP8PcfGG9evR77M8wTypeLxGpotARqssJCYGaLzXWmM5g4euQopk+bDj8fXwT6+RNnP
1y7cg2rVq1BgF8AAv0D8EXY59i3Zw9ePH0m/Bkm04QiiVwDovlO8Dd58vgJrl+7hh1bt6Fr164YN2Ys
gfnj6NHj8PHydqHeXl6Y+vU3uHj+PGKjY5CbnbOzg1Jl68YVyCCWaaDWGmEgusFktrrS3NwKP28vTPc
dj61L52DK2DGYOGEithHdcvzYScyZPQd79+zF2tVrMH70KMwK8sLW5fMxf+5cY4faRs5dhUqPdqkGUr
kOeqPZ2R2unD51Gj4DPsMOn9449sVQTB3+GdauWYtzZ89DpdYhP78Ihw8fhY+3D0IGfoztQYOwz783f
If0hKsrUrLqb1AZIoNApIBGZ4bO8ENfV1ZUwW94P7ycPwoJy0bjm9F90EqiurpMrtSjTaSG87/58xbK
Z47oijeLxyNq0QiEek00/Wa6nTlzplN8Ws3Aynrmrupazu2qBnbs1ev3+LND/e2z/MY57t57QqquZ92
prGXuziokDXZ+7/xvz85dXWfOnJmx0G+0efHMqczDBw8Ffg9k2YKUN2tSDgAAAABJRU5ErkJggg==
'''

icochiudi = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAATCAAAEwgG8z5AYAAAAB3R
JTUUH1wwbFgwO0qEGYQAAAAZiS0dEAP8A/wD/oL2nkwAAA/tJREFUeNq1kl9oHFUUxr/7Z2Z3NtmQCk
1JpKRNSZegYBIjRBpIRdKG4EOMhZoGoa0QNKIoSvyDiKAUK2KNT3mQUvrUp/pYaShIFYmi1tokJjZrw
m5TRchusrvZndm5M+OZ22xa1iLinwMfc7hzv9/59uzgv6ggCELtINVXzhgJmXPndnuzs6fXp6Z6VDbL
g4qB9Hf7e/btC7b19/+8urzcv3t8PCVB5S0vTRoHD+4XXV3gnvfX6XD38qREwffbVj89/xGAIQ1Onj3
bG2/YAVUu49+UE49jZWm5H1QanJ1fkEYmc+tnMYZ0XR1Az525HJjv3z055/peWDvX18Foz0wIFG3b3A
J7JHdjAyHCTiSw/8ABMAJ/feEC6pJJoBpO0FxLCx4ZGNB/3A8XLyK6sABumvAqV0hQm2BFSuzdSz6uw
V00wG5thSqV9DuS7kt01tnXp6F0V3sq7xRjVeBCAWXSwpkzsNNpCulrY1tvL9DZCWUXtfyODiR6euB5
HpRSKKVS2kNeDdaJt1ZBU91iUYPCujoxgfvGxiCbmvTZru5u3JRc940PPhRCda9WVjA3OYnAdaE5jgP
vzsS+lHoV5YrW1jB36n2oG6kQotM3tHdi+wMdYUotfyWNhY8/gMqtwaWkPBKBm8+hbNt3JBYca4uLEJ
YFI2YhahmADyRPvYM9z78Kv6GpMkAnjeUyuHF6AtKz4eTWkf89i+TMTxCmAbfs3Ab7BM5cuwaPklhRg
Xh9hGTBr41i+ovP0f74kxpagV+59BnEpfNwii5KxCmGIRXAYtHqVQiAAcSHKTwIVQR38lh/7Cl0DA3r
lKQt+K6BJ+AcewVWjYGoCUQM8knyS14N5tQxSAmtiGXCH30NDx8fgxBCf3p1N+dQ/9t8OEDDE4MjCEb
fhElrMwhshGAzBOM2OBCcuAQOE1ME68W3CfocJE3hnBN0FvzDIzAnRtCQWSSQoXX/4aOoffkEDPLQfM
g/J2a646TG199F97FnQqMGx1I/Qp08jBi3UWs4Gr59NYloNArTNNF+5Gnc+8ZJ7RUSBEYVePOguWWPT
ql1/Xtk3zoE5tpg4WwSUw6cEzQoPYtIJKLvNTU334KFnEpi2hkLDK7BfgBMjw4j/81l2Fe/wvJLg3BL
NsoKKDpAoQQ4ZcC1Hfw6PgQ1M42Nb7/Ed88Oay8TrMKFJFnbEq1+tjAjOBnBgStjh1ATBWIWQYQJZ3M
o8wEPQJmTAh/zLwxiwwYCRqAaCyJWC99bUxWwo1j8cn1726PO0i+QJhEiBDAJSrIN6kmSIyw9QEkC05
kyCWoBPAZYZhyZPIOr/CkNZox57zU2jtiFwiekPlqNxD8oITMqAKYCpY7j/6w/AJawBs33otZsAAAAA
ElFTkSuQmCC
'''

icocontatti = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAB9ElEQVR42syPAw8cURRGN7Vt27Zt2za
C2g4Xb6a2jaAKy6h2+z/qwer03Ukb1etNzsO93577xgekhV8W8+TJs7xq1aqffLr9J0qWLPkxf/78y/
9ZLNIrV66wdOnSP2KaJpUrV/74z2L98/7YcW6QHgtC9FwQpNfCIL0XBemr6bdYzgEvI9n/F88JceyVw
/HXNife2Jx8Y3H6ncXZd19lWOLiVjNCBB86hB45qEc25mOLnU8sdj/9Sud5SYgbT1Wsue2w9o7D+ns2
GzSb71usvfuVljOSENeZqJh5zWH2dYe5N2zm37SZed1i+rWvemgocXGVsYr+Zx2PgZrB522GX7QZfdm
i3uQkxGVGGrQ4GKbtYZeOx1y6nnDodcqhnx5Sc4JKXFxsmEGdXREa7A3TdH+Ylgdd2h5x6aSHVB6bhL
jgYJPywShVVIQaZoQ6uyM0/D6k3KgkxAW0+AeFNIWHmBQdalBcf0nJ4Ubi4jVr1rBjxw6UUhw6dIiTJ
0/KLnepS///xe3ataN+/fp/QjKJifv168fgwYM9ybhx4wQ5S016ksmxFw8fPpzRo0d7kqlTpwpylpr0
EhN36NDhby+WzP+J8+TJ82H+/PlMmjSJyZMne5K5c+cKcvZqEyZMQDLfBqxBPpDi4gKQBkJVE1RNAS6
DaYIBxi2mPYrvSLkAAAAASUVORK5CYII=
'''

icofoto = '''
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
'''

icoindirizzi = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAABwlBMVEUAAAD///8AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1PD5GSkouNDYyODg0ODo2PDw2PD44Pj48QkJCRk
RGSkhGSkxGTExITEpKTkxOUE5OUk5QVFBSVFBUWlo6PTo8Pjs9Pzw/QD03Ojo6Pjs7PTs+QD5VV1ZWW
Vg5PDs6PTwpLjAtMjMuMzQvNTYwNDQxNjc0Nzc0OTo1OTk2OTg2PD09OzdBRURJYABMS0dOJgBOUU5Y
KwBYVlBZYQBbW1ZbXFxbXVxdXl5dZABdagBeYGBjY2NjZGNlZmZlZ2dmZmZnaGhna2loMwBoaGJpamZ
sb2xxc3F4eXN4enV5e3F9f3WBPgCBg3mFhnyJioCNRACNjoSRkoeSRgCWlouXSQKcdz+dTQSgTQCgoZ
6hTgCkfUSoUgKpgkirhEqsUwSsYgmvsK2zi1C2jVK4WQW7WwHDXgLExsbFYQHFx8fJy8vKzMnMaAfOz
s7O3M7Pz8/S1NTU1tbWZwXW1tTX2dnc3tre3t7e6//f39/g4uLg4+Dh4+Pj4+Pl5+fn6Ojn6ens7Ozu
7u7y8vL29vb4+Pj8/Pz+/v9LDIF4AAAAMHRSTlMAAAEDBAUHCQsNDhATFRYZfHyAgICAgICAgICAgIC
AgICAgIDz8/v7/f39/f39/v4jF3Z2AAABG0lEQVR42mNgxAqQhBWVsAkrqKkrYQrLabu6asszmts4IA
tLaXrX1PloyWb0ViEJS+q7l1VWVrjrhTa1IIQlNHxbu4Gg3d8yrAAuLG7hVd8MBg1uZoEwYRHTgP6JU
DDBz0QUIixkpNvRAwddOobCIGEZK9VJU5DAZBVjMaCwsmBkHwqIFJAGmx01JTU1dYp9UJAjmBEFtTKm
L2tqVl90enp8X87UnL4YqHDslNzc3ClJJSWZU4pyi6bEQoXj+grbCvvyqxuL+4raivrioMIJU4qKiqa
klZbmgRkJUOFEsANSysuzwYxEqHAyyLm1tp4ezp0gVjJU2MnJKTjcAAwiQlzsrPEJMzGzsrFzcHHz8P
Hz8nBzcrCzsTAxAADm/XIknp8IMwAAAABJRU5ErkJggg==
'''

icomodifica = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAADk0lEQVR42mKgBrgaEeB+zt39+wV3940
nk5JkkOXEgNiOHJwTxBTyZqPshyv+lv9OKCn9nyUv/7BVTEwKZrDPfzLAzy+AxukBZpIkgALw/Wsbv3
LjWdu2bXv3bJvhaW3btm1rNhOsdzzNsd5VVf7eTE8yne3kxfn61avUK3BnmuLkojy0rmfGugoVsKN0a
cwuVmyuAg9KpVJwud1wezzw+nzw+f3wcxw4ngcvCBBoRBGiJLHwfge85zrh3uZCNG9iRm5uLiZ3y0ns
blMs+XmxYj+q4HSUIyhPUAqKRaAky5BJJEmA+9JIPNuvQ5d2Zuh0OnRvUSzxaEPx+MZfS60lXsfXUxC
YoaqWBJQUMBBAgCQYDMJ763NwZ5tiZP/6MJlMaFmvLG6vKpY88Hep08QaR6JXbaygrGU6SLBgKIQQid
c2F/KVDvhoSktYLBbUN1fBpSWlcHp+aXvpUm99SqxWJDkqOB0lR1YaMjAcDkN4ugvBG30x++eeDLUac
3H4n5K4u1mHqhVzNhFnKEkJCqrgTFQBI5EIJNdlBO6Mw5YFw2G1WmE26bDpt9Kwb6uJ776cDmLMJSlP
sUw4Kxrk7Ajefxfntk1G48aNCGrC/C/K4enuyvji/YH46quvKDw6zVPDUgYajUYRkhyQH3yOO4ffQYv
mTdkEv86sAse+CvhyVhuMHz8et2/fpvCArLBctClrStBISIRs+x5PLn6GLh2bM/SD0bXgPlgOP71rRf
fu3bF//37E4/Gs8AAACBRdFD1+NBKGaPsD7lvfoV/Plgwd06+ANC2Hfz7LRaNGjTB79mwkEgkabTiYN
oFg+xPC/S8xdkgLhvbprMPTneWx5pfKyM/PxzvvvENnY2gsFtOGlbai34EXlz7AO2PrM7R9SwMebqqI
w/9VQPlypdCsWTPcuHEDL1++ZHE4HNqw0tb55A7s1zfgw+l90aShCVdWVMbDzTXQoqkFM2bMgM1mA32
pyWQSPM9h69YtPHsYWeFIhMGPrqzHtYNf4cTaPji4sCGil+uCc97HQ9tDCqrQtevW8nq9fgx7bdlgOs
PzZ0+wceE7OLNpOE5tGAb71dUISS4GPXv2TIUuWbqELygoGK2gmvCaVSvQolljnD+8BCHZzxCCsUuie
75GlyzmcnNzRyqoJkxnOHn8CHw+D4VYMmF2/LVrONJUhWrA2h/9gcvlIhe1lTMYDCNUqMb3NsnIN0zr
N0H/BwqZ8W4FlNUHAAAAAElFTkSuQmCC
'''

iconuova = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAC/ElEQVR42qTVQ3gsWRwF8PNQPezdi7k
Z27Ztc5vZjGfWY9u2J7Zt27addp9Xt9K3GnFS33eCwu87938bILmj4HMcwPd4Zv9P++vDfw+fCPsvbH
7/9/sr1XMvIweKvE8ckWqu3FZOwZ34AiPXFF7Db7u+5bctalq/1f6+JuMa4kN04Rf4S/jKwaFhDo+Mc
GR0jGPj4xyfmODk1JSWqelpTs/McHx6nCf8cQIvzriYr3W/xqcKoiiPZ4qi+Lp6TlxTVzQgVqXBwyOj
HB0T6AQnJie9wJnZWc7OzfHVyldp+M3A+2vv55OtD/Ge5Kt0+NG0q/hc10N8uO5+GqINxDd4XoMFKlv
6gnPz85xXc8bfZ1D5U2HA9/48+/dwnv2hnw5f9qkfb/gnnKf+6k/lb4X4Do0a7IvOquicigpwYWGBi4
uLNH5vJN4GtzoOvAvReEyDJerV0gUuLS1xaXmZAf8HEO9sDSsfgvgLcxqso54tXeDyygpX1JycfjIRA
x79BXj8j+BZH0DHrv0MvPav1fP7/wPxH2o0eEYsX6JqS4Euq6gATSYTzWYz321/l0gAEQeekAVe8Jcb
vjUWvLUcDEwDkagmFi9osFy+bCpRAVosFlqtVposJkZmRxLRoOF/MOInN3zGnyqapDUl0tGG36Fo8Br
UZPJEtdhsNg4vD/PEshOJtNXmyg+gQSw/ztW0AANIQID+BtE3yqOpLypit9tpspr4dvfbPKv6LBqLjQ
wsDiSS0YtsPItOHBCoDi+4dl/OVKC+oIjD4Vg3wpCgFyzaihHIjfJs6os6nU7fbAzrbeUItkDF3+K6L
LAh7LlhniPwRcV9ra2trKqqYklJCYuKihgdHT0E4PiNYDGGDdvKptXV1V6tCwsLTCEhIRdIbC28wRg8
24r/8/PzdbS0tMR61lmnXiGQDWExX99N820rzmdkZGjnSkqKrZdffvlNAtguLNB1YXFPWlq62jrPdNZ
Zp10ugT3D4iX566+/DoeFhZ27Fbrz7zzg8JSIrXQBclGELYBwFBUAAAAASUVORK5CYII=
'''

icosalva = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAA
DdgAAA3YBfdWCzAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKbSURBVHjatZ
VdaxNBFIbf3U2CERpv9Cbpl5Sair0VxY9rFf0dFryRWj/Ab+pNQUjxF6g/o4K/QOidSEhKQWuRgtuau
JndnZ1Z58zEYZYgFkLfcOacsHOeffdsduPleY6jUImWG9eub0dRNOsHPu6uPEJZZbgn9D0AHjxPryBR
bbKHhGdYf70GKSTm5uZ23r5/N6XBAzaYXV5eRndrC+cvXcWJ48cwxBLGgizcAFWY/Cti6H75DCEENj5
sTFrHUkq01ltonmmCZ5ky6FmwhReBFkoXwzOJTqejwVLmsGCac6aAdAKClss+Nj51cRjdvDCPHDn1Ui
iWRMHxQnNBn8DzFTjwcOviPFypQwQwOTdZqoXmK4Qkt8axkEXHBKdLo00szfBxcxuH0ZXFKWQyJ6hxr
ViuYzpgwKpmSYbL56Zg3ZrVuB3al0PncWodm1HIfzjOBG3m2Oz8wGG0OHvKgjUnd8F0CUJQaR2fnT45
AsmNCVM7jrmgfgN2HdNcNJDEucCwhKdhVhY6ciMBZGTMsFzHZhSk1ft3MIaI5Tq2oxhbZHDU8fgafUD
oyfurl69WUavV/uts6fYS+v2e7p2eND9PIRww/VQ457YpDEM8ffwEaZqiWq3i2YvnsHJeAY16HXt7JR
zs79t+IbIiOOO80MiiiJqpdmEEoKxDcE4HQB/qD4KAWA5YCnqrFR0JocNTrgeDgQu1kXBu32jUX2808
HXnm3PzhJQxY36ppL8iSRIFScHiGBVRUXPsW6gbLGZqb0y1dtzv9YqOfS+49zMMW7WJCYJr0MqDh0h5
qm9STzU4QOt+8DtCzGLwNAWvVLC7u1sEd7a7b07PzCA82G8hh99ut1FRG+3zL6UNV98VKE0TXTPGDLB
ciigf2Z/pH6S7UJf/7+KAAAAAAElFTkSuQmCC
'''

setico = {"anagrafiche" : [icoanagrafiche, "Menu gestione anagrafiche"],

          "annulla" : [icoannulla, "annulla l'inserimento corrente"],

          "cancella" : [icocancella, "Cancella l'anagrafica corrente ed i dati associati"],

          "cerca" : [icocerca, "permette di effettuare una ricerca tra le anagrafiche"],

          "chiudi" : [icochiudi, "chiude l'applicazione"],

          "contatti" : [icocontatti, "avvia la gestione dei contatti associati"],

          "foto" : [icofoto, "associa una foto alla anagrafica corrente"],

          "indirizzi" : [icoindirizzi, "avvia la gestione degli indirizzi associati"],

          "modifica" : [icomodifica, "permette la modifica dei dati anagrafici correnti"],

          "nuova" : [iconuova, "avvia l'inserimento di una nuova anagrafica"],

          "salva" : [icosalva, "registra i dati inseriti"]
          }


class IcoDispencer:
    def __init__(self):
        self.icoset = setico

    def getIco(self, chiave):
        return self.icoset[chiave][0]

    def getDescr(self, chiave):
        try:
            descr = self.icoset[chiave][1]
            return descr
        except:
            return None

    def printData(self):
        for chiave in self.icoset:
            print(chiave, ':', self.icoset[chiave][1])

    def getData(self):
        return self.icoset

Offline paolodecaro

  • python unicellularis
  • *
  • Post: 21
  • Punti reputazione: 0
    • Mostra profilo
Re:Tooltip in tkinter
« Risposta #3 il: Gennaio 15, 2020, 14:09 »
Buonasera NuzzoPippo, ho provato il tuo esempio. Non ho capito però una cosa , abbandonerai Tkinter per altri framework visuali ? mi tieni informato.
Grazie
Paolo

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 274
  • Punti reputazione: 0
    • Mostra profilo
Re:Tooltip in tkinter
« Risposta #4 il: Gennaio 15, 2020, 16:25 »
Ciao @Paolo

Si, anche se ho ancora un po' (forse un bel po') di base da vedere, ho intenzione di cominciare a fare "qualcosa", in python, e l'unico target che credo mi sia accessibile, principalmente per le mie limitazioni culturali, è nell'ambito dei gestionali di tipo desktop, quindi penso sia ora di mettermi a studiare le GUI, sin ora ho guardato superficialmente tkinter e lo trovo nel complesso insoddisfacente, lo abbandonerò una volta studiatomi sufficientemente uno sviluppo con i pattern MVC/Observer in tale ambiente e realizzato una "tabella" decente.
 ... magari, se avrò tempo, metterò on-line un paio di piccoli script (completamente al di fuori della pep8 e dei canoni mvc) che ho realizzato con detto framework, giusto se possano servire a qualcuno, notizierò nel caso.

P.S. - il sistema dei tooltip per i menu lo ho esteso ai menu aggiunti con "cascade" ed è probabile decida di estenderlo anche agli item tipo check-button (per alcune opzioni di ricerca), magari posterò anche tale evoluzione, anche se un po' ozioso, la metodologia è già dentro quanto postato.

Ciao :)