Controllo avanzato dei widget
Widget particolari
Presenteremo in questa sezione alcuni widget utili, illustrandoli con semplici esempi.
Pulsante con icona
Ad un pulsante può essere associata un'icona. È sufficiente caricare un'immagine (in formato GIF) e poi associarla al pulsante tramite la proprietà image.
self.imq=PhotoImage(file='exit.gif')
self.QuitButton=Button(
self.parent,
image=self.imq,
command=self.Quit
)
self.QuitButton.pack()
Pulsanti di selezione e di opzione (radio buttons e check buttons)
I pulsanti di selezione e di opzione si ottengono con i widget Radiobutton e Checkbutton, rispettivamente, associati a variabili di tipo IntVar
o BooleanVar
.
self.quality = IntVar()
self.quality.set(10)
f=Frame(self.parent)
self.qualityRadiobutton_Low=Radiobutton(
f,
text='low quality',
variable=self.quality,
value=10
)
self.qualityRadiobutton_Middle=Radiobutton(
f,
text='middle quality',
variable=self.quality,
value=20
)
self.qualityRadiobutton_High=Radiobutton(
f,
text='high quality',
variable=self.quality,
value=30
)
self.qualityRadiobutton_Low.pack({'side':'left'})
self.qualityRadiobutton_Middle.pack({'side':'left'})
self.qualityRadiobutton_High.pack({'side':'left'})
f.pack()
self.full=BooleanVar()
self.full.set(False)
self.fullCheckbutton=Checkbutton(
self.parent,
text='full example',
variable=self.full
)
self.fullCheckbutton.pack()
Menù di opzioni
Nell'esempio che segue vediamo come si possono impostare alcune proprietà dei widget attraverso un menù di opzioni.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.propertyname = StringVar()
self.propertyname.set('foreground') # valore di default
self.propertyvalue = StringVar()
self.propertyvalue.set('green')
self.parent = parent
properties = ['background',
'foreground',
'activebackground',
'disabledforeground',
'highlightcolor',
'highlightbackground',
'width',
'height',
'padx',
'pady',
]
self.PropertyMenu = OptionMenu(parent, self.propertyname, *properties)
self.PropertyMenu.pack()
self.MyInputBox = Entry(parent, textvariable=self.propertyvalue)
self.MyInputBox.pack()
self.MyButton = Button(parent, text="Fai clic qui")
self.MyButton['background']="#FFFFFF"
self.MyButton['foreground']="red"
self.MyButton['command']=self.MyButton_Click
self.MyButton.pack({"side":"top", "padx": 10, "pady": 20})
self.StatusBar = Label(parent, text="...")
self.StatusBar['background']="#FFFFFF"
self.StatusBar['foreground']="blue"
self.StatusBar.pack({"side":"bottom", "expand":"yes", "fill":"x"})
def MyButton_Click(self):
print('name:', self.propertyname.get())
print('value', self.propertyvalue.get())
self.MyButton[self.propertyname.get()]=self.propertyvalue.get()
def main():
root = Tk()
myapp = Application(root)
root.mainloop()
if __name__=='__main__':
main()
Regolatore
Un regolatore consente di variare il valore di una variabile facendo scorrere una sorta di manopola.
self.quality = IntVar()
self.quality.set(10)
self.qualityScale = Scale(
self.parent,
variable=self.quality,
from_=0,
to=60,
orient=HORIZONTAL,
length=200,
sliderlength=15
)
self.qualityScale.pack()
Caselle di testo multilinea (con barra di scorrimento)
Le caselle di testo possono essere multilinea e consentono un sacco di operazioni (estrazioni di parte del testo, sostituzioni, formattazione, ecc.). Esempi e documentazione si possono trovare nel Tk Tutorial.
Alle caselle di testo, così come ai canvas e ad altri widget "grandi" possono essere associate le barre di scorrimento (verticali o orizzontali).
Una barra di scorrimento ha un doppio legame con il widget associato (bisogna impostare il parametro command
della barra alla funzione yview
o xview
del widget e il parametro yscrollcommand
o xscrollcommand
del widget alla funzione set
della barra). Può essere conveniente inserire widget principale e barra di scorrimento in un frame:
self.lyricsFrame=Frame(self.parent)
self.lyricsText = Text(self.lyricsFrame,
width=80,
height=4
)
self.lyricsText.pack({'side':'left'})
self.lyricsText.insert("1.0",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nNam consectetur dictum nisl, eget blandit magna suscipit tristique.\nFusce sit amet nunc eu lorem varius luctus ac id eros.\nClass aptent taciti sociosqu ad litora torquent per conubia nostra,\nper inceptos himenaeos.")
self.lyricsScrollbar=Scrollbar(self.lyricsFrame)
self.lyricsScrollbar.pack({'side':'left', 'expand':'yes', 'fill':'y'})
self.lyricsFrame.pack()
self.lyricsScrollbar['command']=self.lyricsText.yview
self.lyricsText['yscrollcommand']=self.lyricsScrollbar.set
Casella di elenco
Una casella di elenco contiene un elenco di opzioni tra cui l'utente può scegliere (tipicamente preso da una tupla o da una lista). L'indice o gli indici degli elementi selezionati partono da 0.
La casella può essere di tipo single, browse, multiple o extended, a seconda del numero di elementi selezionabili e dalla modalità di interazione possibile.
self.fruitListbox=Listbox(
self.parent,
height=5,
selectmode='extended'
)
self.fruits=('apples', 'oranges', 'strawberries', 'bananas', 'lemons')
for f in self.fruits:
self.fruitListbox.insert("end", f)
self.fruitListbox.pack()
Canvas
Un canvas è una tavolozza dove si può disegnare.
class Application(object):
def __init__(self, parent):
self.Canvas = Canvas(parent, width=300, height=400)
self.Canvas['background'] = 'white'
self.Canvas.pack()
self.r1_id = None
self.MyButton = Button(parent, text="Fai clic qui")
self.MyButton['background']="#FFFFFF"
self.MyButton['foreground']="red"
self.MyButton['command']=self.MyButton_Click
self.MyButton.pack({"side":"top", "padx": 10, "pady": 20})
self.StatusBar = Label(parent, text="...")
self.StatusBar['background']="#FFFFFF"
self.StatusBar['foreground']="blue"
self.StatusBar.pack({"side":"bottom", "expand":"yes", "fill":"x"})
def MyButton_Click(self):
if self.r1_id:
self.Canvas.move(self.r1_id, 2, 5)
else:
self.r1_id = self.Canvas.create_rectangle(2, 10, 8, 20)
Posizionamento dei widget
Vedremo con tre esempi semplicissimi come posizionare i nostri widget nella finestra utilizzando le tre modalità che Tkinter ci mette a disposizione. Il nostro obiettivo è di avere una serie di nove pulsanti numerati.
Pack()
Con il metodo pack()
specifichiamo dove mettere un widget in relazione agli altri (a sinistra, a destra, in alto, in basso). Può essere comodo avere dei widget invisibili (frame) che ne contengono altri.
class Application(object):
def __init__(self, parent):
self.UpperFrame=Frame(parent)
self.MiddleFrame=Frame(parent)
self.BottomFrame=Frame(parent)
self.b1 = Button(self.UpperFrame, text="1")
self.b2 = Button(self.UpperFrame, text="2")
self.b3 = Button(self.UpperFrame, text="3")
for widget in self.b1, self.b2, self.b3:
widget.pack({'side':'left'})
self.b4 = Button(self.MiddleFrame, text="4")
self.b5 = Button(self.MiddleFrame, text="5")
self.b6 = Button(self.MiddleFrame, text="6")
for widget in self.b4, self.b5, self.b6:
widget.pack({'side':'left'})
self.b7 = Button(self.BottomFrame, text="7")
self.b8 = Button(self.BottomFrame, text="8")
self.b9 = Button(self.BottomFrame, text="9")
for widget in self.b7, self.b8, self.b9:
widget.pack({'side':'left'})
self.UpperFrame.pack({'side':'top'})
self.MiddleFrame.pack({'side':'top'})
self.BottomFrame.pack({'side':'top'})
Grid()
Con il metodo grid()
organizziamo la nostra finestra come se fosse una tabella, e inseriamo i nostri widget all'interno delle diverse celle.
class Application(object):
def __init__(self, parent):
self.parent= parent
self.digitButtons = []
for digit in range(9):
digitButton = Button(parent, text=str(digit+1))
digitButton.grid(row=digit//3, column=digit%3)
self.digitButtons.append(digitButton)
self.QuitButton=Button(parent, text='quit')
self.QuitButton['command'] = self.Quit
self.QuitButton.grid(row=4, column=4)
def Quit(self):
self.parent.destroy()
Place()
Con il metodo place()
indichiamo esplicitamente dove posizionare i widget, specificandone le coordinate in termini assoluti o relativi.
class Application(object):
def __init__(self, parent):
self.parent= parent
SCALE_X=30
OFFSET_X=10
SCALE_Y=40
OFFSET_Y=60
self.digitButtons = []
for digit in range(9):
digitButton = Button(parent, text=str(digit+1))
digitButton.place(
y=(digit//3)*SCALE_Y+OFFSET_Y,
x=(digit%3)*SCALE_X+OFFSET_X
)
self.digitButtons.append(digitButton)
self.QuitButton=Button(parent, text='quit')
self.QuitButton['command'] = self.Quit
self.QuitButton.place(relx=0.7, rely=0.8)
def Quit(self):
self.parent.destroy()