| 4 | ||
| Editor: geon Time: 2011/10/12 18:27:43 GMT+2 | ||
| Note: oprava | ||
changed: - ..aneb co se v dokumentaci těžko hledá... .. image:: py25.png :align: right 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()
..aneb co se v dokumentaci těžko hledá...
 
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()
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()
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
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
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))
"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')
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()
text.get(INSERT) # zjisteni text.mark_set(INSERT, "2.7") # nastaveni
widget.event_generate("<Motion>", warp=1, x=..., y=...)
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
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()
# -*- 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()
from Tkinter import *
okno=Tk()
okno.wm_state('zoomed')
mainloop()