..aneb co se v dokumentaci těžko hledá...

py25.png

Bez černého konzolového okna

Pokud nechceme, aby se otevíralo černé dosovské okno, stačí dát příponu programu *.pyw nebo ke spouštění použít místo python.exe pythonw.exe. Nevýhoda tohoto způsobu při vytváření aplikace je jasná: neuvidíte případné chybové hlášky a nebudete moci ani používat print.

Řešením tohoto problému nicméně může být přesměrování stdout a stderr do okna. Následující příklad to dělá. Okno pro výpisy je po spuštění zavřené a otevře se až v případě zápisu do stdout či stderr. Výpisy na stderr zobrazuje červeně. Okno je možné zavřít, v případě potřeby se zase otevře. Příklad

import sys
from Tkinter import *


hlavni=Tk()

_printtext = None

def getprinttext():
    global _printtext
    if _printtext == None:
        printwin = Toplevel()
        def reset():
            global _printtext
            _printtext = None
            printwin.destroy()
        printwin.protocol("WM_DELETE_WINDOW", reset)
        _printtext = Text(printwin)
        _printtext.pack(expand=True, fill=BOTH)
        _printtext.tag_config('out', foreground="black")
        _printtext.tag_config('err', foreground="red")
    return _printtext

class FakeStdOut(object):
    def write(self, what):
        getprinttext().insert(END, what, 'out')

class FakeStdErr(object):
    def write(self, what):
        getprinttext().insert(END, what, 'err')

oldso = sys.stdout
oldse = sys.stderr
sys.stdout = FakeStdOut()
sys.stderr = FakeStdErr()

def so():
    print 'aaaaaa'

def se():
    print >> sys.stderr, 'bbbbbbb'

try:
    Button(text="stdout", command=so).pack()
    Button(text="stderr", command=se).pack()
    Button(text="Sbohem", command='exit').pack()
    hlavni.mainloop()
except SystemExit:
    pass
except:
    sys.stdout = oldso
    sys.stderr = oldse
    import traceback
    traceback.print_exc()

Schování widgetu

Ukrytí widgetu se dá udělat pomocí metody widget.pack_forget() a následné zobrazení pomocí widget.pack(). U grid manageru je to widget.grid_remove() a zobrazení pak s widget.grid() a mělo by to být na tom samém místě.

Ukázka:

# -*- coding: utf8 -*-
"""Ukazkovy priklad v Tkinter."""

from Tkinter import *
priznak=True

def tisk():
   global priznak
   print priznak
   if priznak:
       listbox.pack_forget()
       tisk['text']='Zobrazit!'
   else:
       listbox.pack()
       tisk['text']='Schovat!'
   priznak = not priznak

hlavniOkno=Tk()
hlavniOkno.title('Aplikace v Tk')
ramec=Frame(hlavniOkno)
ramec.pack()

listbox=Listbox(ramec, selectmode=MULTIPLE)
seznam=['Python','C++', 'Java', 'Pascal', 'Basic']

for prvek in seznam:
   listbox.insert(END, prvek)

listbox.pack()
tisk=Button(hlavniOkno, text='Schovat!', command=tisk)
tisk.pack(ipadx=40)

mainloop()

Změna systémové ikony

Tak na tohle má Tkinter metodu iconbitmap. Použití je např. následující: root.iconbitmap("cherry.ico"), cherry.ico je soubor s ikonou ve formatu *.ico

Okno pořád na vrchu, okno nejde zavřít

Chcete aby bylo okno pořád vidět, aby se nedalo schovat za ostatní? a ještě aby nešlo standardním způsobem (křížek nebo Alt+F4) zavřít? Použijte následující kod:

root=Tk()                                      # okno
root.protocol('WM_DELETE_WINDOW', 0 ) # aby nešlo zavřít, místo 0 možno použít nějakou funkci na případnou hlášku
root.protocol('WM_TAKE_FOCUS', root.update )   # aby se stalo aktivním
root.wait_visibility(root)                     # aby fungoval následující řádek
root.attributes('-topmost',1)                  # aby bylo pořád navrchu

Okno bez rámu, bez ikony, bez title a bez ovládacích prvků

from Tkinter import *

root = Tk()
Label(root, text='No wm decorations').pack(padx=10, pady=10)
root.overrideredirect(1)
root.mainloop()

Pokud ještě potřebujete zobrazit aplikaci přes celou obrazovku a neznáte předem rozlišení, je možné přidat v předchozím kódu před mainloop():

w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d%+d%+d" % (w,h,0,0))

Hromadná změna vzhledu u všech widgetů

"Ošklivý" vzhled standardního vzhledu Tk oken můžete změnit pomocí databáze voleb (option database). Dá se to provést buď přímo v programu:

# -*- coding: utf8 -*-
from Tkinter import *

hlavni=Tk()

hlavni.option_add('*background','#797778')
hlavni.option_add('*Font', 'Verdana 20 bold')

# dalsi moznosti
# hlavni.option_add('*background','#797778')
# hlavni.option_add('*foreground','#fdfd02')
# hlavni.option_add('*EntryField.Entry.background', 'white')
# hlavni.option_add('*Entry.background', 'white')
# hlavni.option_add('*MessageBar.Entry.background', 'gray85')
# hlavni.option_add('*Listbox*background', 'dark green')
# hlavni.option_add('*Listbox*selectBackground', 'dark slate blue')
# hlavni.option_add('*Listbox*selectForeground', 'white')

w=Label( text="Ahoj světe!")
w.pack()

mainloop()

nebo načtením z externího souboru s nastaveními:

*font : Helvetica -12
*Entry*background : white
*Listbox*background : white
*Listbox*exportSelection : 0
*selectBackground : blue4
*selectForeground : white
*Scrollbar*takeFocus : 0
*Scrollbar*highlightThickness : 0
*Menu*tearOff : 0
atd.

Když uložíte toto jako "optionDB", tak pak následně v programu můžete nastavení načíst takto:

root = Tk()
root.option_readfile(<cesta-k-optionDB>)

Tk podporuje i barevná schémata. Následující kód nastaví modrý vzhled, ostatní barvy se vypočítají tak, aby byl zajištěn barevný kontrast všech prvků uživatelského rozhraní:

root = Tk()
root.tk_setPalette('blue')

Scrollování kolečkem myši

Scrolování textu pomocí kolečka myši umožňuje nedokumentovaná událost na Linuxech 'Button-4' a 'Button-5' a na Windows <MouseWheel>, kde existuje atribut 'delta', který udává směr.:

import Tkinter

def priRolovani(udalost):
    print "udalost:", udalost,"  ---  smer:", udalost.delta

okno=Tkinter.Tk()
okno.bind('<MouseWheel>', priRolovani)
text=Tkinter.Label(okno, text="SCROLUJ a ROLUJ!", font="Arial 20")
text.pack(padx=40, pady=40)

okno.mainloop()

Poloha kurzoru v textu

text.get(INSERT)  # zjisteni
text.mark_set(INSERT, "2.7")  # nastaveni

Místní nabídka aneb menu na pravém tlačítku

from Tkinter import *
root = Tk()

def hello():
    print "hello!"

def popup(event):
    menu.post(event.x_root, event.y_root)

menu = Menu(root, tearoff=0)
menu.add_command(label="Undo", command=hello)
menu.add_command(label="Redo", command=hello)

frame = Frame(root, width=512, height=512)
frame.pack()

frame.bind("<Button-3>", popup)

mainloop()

Ovládání kurzoru myši

widget.event_generate("<Motion>", warp=1, x=..., y=...)

Aby podokno bylo aktivní

podokno.focus_set()         # aby bylo okno aktivní
podokno.transient(hlavni)   # je považováno za dialogové okno  - s minimalizací hlavního okna
                            # se minimalizuje také, není vidět na hlavní liště
podokno.grab_set()          # aby nešlo zpátky přepnout do hlavního okna, dokud se neukončí podokno

Vycentrování okna na střed obrazovky

from Tkinter import *
root = Tk()
w=root.winfo_screenwidth()
h=root.winfo_screenheight()
sirka=400
vyska=200
root.geometry("%dx%d+%d+%d" % ( sirka, vyska, (w-sirka)/2, (h-vyska)/2 ) )
root.mainloop()

Přesměrování výstupu do okna

# -*- coding: utf-8 -*-

from Tkinter import *
from ScrolledText import ScrolledText
import sys

class py_message_box:

  def __init__(self, parent):

    self.frame = Frame(parent)
    self.frame.pack()

    self.text = ScrolledText(self.frame, background='black',
                foreground='green', font=("Courier", 9))
    self.text.pack()

  def write(self, s):
    self.text.insert(END, s)
    self.text.see(END)

root=Tk()
text_window = py_message_box(root)
sys.stdout = text_window
sys.stderr = text_window

for i in range(44):
    print i, "Toto je pokus o presmerovanie printu do okna"   # toto se vytiskne do GUI okna
print tojealechyba  # a toto taky

root.mainloop()

Maximalizace okna (win)

from Tkinter import *
okno=Tk()
okno.wm_state('zoomed')
mainloop()