Rendez-vous sur Arrakis

tk and tkinter snippets

Tk est génial pour faire des interfaces graphiques ! Il est léger, rapide et surtout très pratique pour coder.

En python :

from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk

Barre de progression en tk

    canvas=Canvas(parentframe, width=300,  height=20,  bg='ivory')
    canvas.configure(bd=2,  relief='groove')
    canvas.pack()
    perc = float(perc[0].strip("%")) # this is a percent
    canvas.create_rectangle(0, 0, perc/100*300, 20, fill='green')
    canvas.update()

Récupérer le presse-papier et le mettre dans une saisie

try :
    c = self.root.clipboard_get().strip()
    if c:
        self.entry.delete(0, END)
        self.entry.insert(0, c)
except:
    c= ""

Avoir une fenêtre pour choisir un fichier

    def chdir(self):
        dldir = filedialog.askdirectory(\
            initialdir=(os.path.expanduser("~")),\
            title="Télécharger dans",\
            parent=self.root)
        if dldir != ():
            self.dldir = dldir
            self.chgbtn.configure(text="Téléchargement dans {}".format(\
                            self.dldir))

Afficher une information dans une popup

messagebox.showinfo(message = txt)

Déplacer des widget dans un treeview

    def bMove(self, event):
    # To move item in treeview
    # https://stackoverflow.com/questions/11570786/tkinter-treeview-drag-and-drop
        tv = event.widget
        moveto = tv.index(tv.identify_row(event.y))    
        for s in tv.selection():
            tv.move(s, '', moveto)

Remplacer zenity

# replace zenity --title=$1 --text=$2 --entry
from tkinter import *
from tkinter import simpledialog
def help():
    print("usage : ")
    print("{} <Title> <Question>".format(sys.argv[0]))
    sys.exit(1)
def main():
    if len(sys.argv) == 3:
        root = Tk()
        root.withdraw()
        ans = simpledialog.askstring(sys.argv[1], sys.argv[2])
        if str(ans) != "" :
            print(ans)
        return 0
    else:
        help()
if __name__ == '__main__':
    main()

Enlever la barre de la fenêtre

self.root.overrideredirect(True)

Centrer une fenêtre

def center(self):
        self.root.update_idletasks()
        w = self.root.winfo_screenwidth()
        h = self.root.winfo_screenheight()
        size = tuple(int(_) for _ in self.root.geometry().split('+')[0].split('x'))
        x = w/2 - size[0]/2
        y = h/2 - size[1]/2
        self.root.geometry("%dx%d+%d+%d" % (size + (x, y)))

Support du systray

Il faut tktray d'installé

class Icon(tkinter.BaseWidget, tkinter.Wm):
    def __init__(self, master=None, cmd = None, cnf={}, **kw):
        if not master:
            if tkinter._support_default_root:
                if not tkinter._default_root:
                    tkinter._default_root = tkinter.Tk()
                master = tkinter._default_root
        self.TktrayVersion = master.tk.call('package', 'require', 'tktray')
        # stolen from tkinter.Toplevel
        if kw:
            cnf = tkinter._cnfmerge((cnf, kw))
        extra = ()
        for wmkey in ['screen', 'class_', 'class', 'visible', 'colormap']:
            if wmkey in cnf.keys():
                val = cnf[wmkey]
                # TBD: a hack needed because some keys
                # are not valid as keyword arguments
                if wmkey[-1] == '_': opt = '-'+wmkey[:-1]
                else: opt = '-'+wmkey
                extra = extra + (opt, val)
                del cnf[wmkey]
        tkinter.BaseWidget.__init__(self, master, 'tktray::icon', cnf, {}, extra)
        self.protocol("WM_DELETE_WINDOW", self.destroy)
        if cmd:
            self.bind("<ButtonPress-1>", lambda x: Popen(cmd))

Changer l'icône de la fenêtre

# set window icon
image = Image.open(icon)
imgicon = ImageTk.PhotoImage(image)
self.root.tk.call('wm', 'iconphoto', self.root._w, imgicon)  

Simple demande d'entrée par l'user

from tkinter import simpledialog
pw = simpledialog.askstring(txt_passphrase,txt_passphrase)

Simple dialog

from tkinter import simpledialog
class Dialogue(simpledialog.Dialog):
    def __init__(self, parent, title=None, other_args=""):
            super().__init__(parent,title)
            self.args = other_args

    def body(self, master):
        frame = ttk.Frame(master)
        titlelabel = ttk.Label(frame, text=txt_configuration)
        titlelabel.grid(sticky=N, column=0, columnspan=2, row=0, pady=5, padx=5)
        wlanlabel = ttk.Label(frame, text=txt_wlanlabel)
        wlanlabel.grid(column=0, row=1, sticky=W, pady=5, padx=5)
        wlan_ifaces = [ i for i in get_ifaces() if get_iface_type(i) == "wlan" ]
        self.wlan_box_value = StringVar()
        self.wlan_box = ttk.Combobox(frame, textvariable=self.wlan_box_value)
        self.wlan_box['values'] = wlan_ifaces
        self.wlan_box.current(0)
        self.wlan_box.grid(column=1, row=1, pady=5, padx=5)
        ethlabel = ttk.Label(frame, text=txt_ethlabel)
        ethlabel.grid(column=0, row=2, sticky=W, pady=5, padx=5)
        eth_ifaces = [ i for i in get_ifaces() if get_iface_type(i) == "eth" ]
        self.eth_box_value = StringVar()
        self.eth_box = ttk.Combobox(frame, textvariable=self.eth_box_value)
        self.eth_box['values'] = eth_ifaces
        self.eth_box.current(0)
        self.eth_box.grid(column=1, row=2, pady=5, padx=5)
        for child in master.winfo_children():
            child.grid_configure(padx=5, pady=5)
        return self.wlan_box # initial focus
    def apply(self):
        wlaniface = self.wlan_box.get()
        ethiface = self.eth_box.get()
        saveconfig("DEFAULT", "wlaniface", wlaniface)
        saveconfig("DEFAULT", "ethiface", ethiface)

Console dans la fenêtre

root = Tk()
termf = Frame(root, height=700, width=1000)
termf.pack(fill=BOTH, expand=YES)
wid = termf.winfo_id()

f=Frame(root)
cmd('xterm -into {} -geometry 160x50 -sb -bg black -fg grey -e "ls; ksh" &'.format(wid))

root.mainloop()

Icône de la fenêtre en base64

    from PIL import Image, ImageTk
    from io import BytesIO
    import base64
    # set window icon
    imgicon = Image.open(BytesIO(base64.b64decode(tkmenuicon)))
    imgicon = ImageTk.PhotoImage(imgicon)