PyQt: Tutorial per iniziare

qttutorial

Ritorna alla pagina <-- Modifica precedente | Modifica successiva -->

Sommario diffierenze
Titolo PyQt: Tutorial per iniziare (WORK IN PROGRESS) PyQt: Tutorial per iniziare (WORK IN PROGRESS)
Data 2009-10-10 16:47:34 2009-10-10 16:57:58
Autore shainer shainer
Tags

2009-10-10 16:47:34 di shainer
2009-10-10 16:57:58 di shainer
82  app = QtGui.QApplication(sys.argv)82  app = QtGui.QApplication(sys.argv)
83  main = MainWindow()83  main = MainWindow()
84  main.show()84  main.show()
85  sys.exit(app.exec_())85  sys.exit(app.exec_())
8686
tt87.. img:: 8
88   :nolink:
89
90Le quattro righe “nuove” sono::
91
92                button = QtGui.QPushButton('Quit')
 >;
93                button.setFont(QtGui.QFont("Times"
 >, 10, QtGui.QFont.Bold));
94                self.connect(button, QtCore.SIGNAL
 >('clicked()'), QtCore.SLOT('close()'));
95                
96                self.setCentralWidget(button);
97
98Con la prima, creiamo un nuovo pulsante con il nom
 >e Quit. La definizione completa di questo costrutt
 >ore è:
99
100*__init__ (self, QIcon icon, QString text, QWidget
 > parent = None)*
101
102Come vedete possiamo definire un'icona da associar
 >e al bottone, la stringa di testo, e il widget “ge
 >nitore”. Nel nostro caso possiamo lasciare il valo
 >re di default, ma vedremo che in seguito tale para
 >metro ci sarà utile. Il metodo *setFont()* è abbas
 >tanza esplicativo.
103*setCentralWidget()*: ogni volta che creiamo una f
 >inestra in PyQt4, essa richiede che sia settato un
 >o e un solo widget come centrale. Se ciò non viene
 > fatto correttamente, non potrete visualizzare fin
 >estre più complesse, con un numero elevato di widg
 >et, e con dei menu/toolbar.
104Per adesso abbiamo creato un solo pulsante, e quin
 >di non c'è nessun problema: cosa faremo, invece, q
 >uando ce ne saranno più di uno? Lo vedremo in segu
 >ito.
105
106Segnali e slot
107###############
108
109La funzione *connect* infine è di particolare impo
 >rtanza. Questa infatti permette di associare ad un
 > segnale (ovvero ad un evento), un particolare “sl
 >ot”, o funzione definita dall'utente. Il primo par
 >ametro definisce il widget da cui deve provenire t
 >ale evento (*button*, nell'esempio precedente), su
 >ccessivamente si definisce il tipo di segnale, e i
 >nfine il nome della funzione (nel codice, uno slot
 > predefinito di *QtCore* che provoca la chiusura d
 >ell'applicazione).
110I segnali rappresentano tutte le azioni che l'uten
 >te può compiere con un determinato widget (nel cas
 >o di un pulsante, l'utente può cliccarlo): nella r
 >eference troverete una lista di segnali accettati 
 >da ogni widget. Nel nostro caso, vogliamo che quan
 >do il pulsante viene cliccato (segnale *clicked()*
 >), il programma venga chiuso.
111Altri segnali saranno visti nel corso di questo tu
 >torial, basta ricordare che per associare un segna
 >le di un particolare widget ad uno slot (o funzion
 >e personale) bisogna usare *connect*.
112
113È possibile anche emettere un particolare segnale 
 >utilizzando *emit*.
114
115Layout
116#######
117
118Passiamo all'inserimento di più widgets.
119Il posizionamento di più widgets all'interno della
 > finestra si può realizzare in due modi: tramite i
 >l cosiddetto posizionamento assoluto, o definendo 
 >dei layout.
120
121Il primo metodo consiste nello specificare la posi
 >zione in pixel di ogni layout: è decisamente scons
 >igliato. Infatti l'applicazione potrebbe risultare
 > diversa su diverse piattaforme, se apportate una 
 >piccola modifica (ad esempio cambiate font) dovret
 >e rivedere tutto, e la posizione non cambia se l'u
 >tente ridimensiona la finestra.
122Tuttavia, se volete usarlo, ecco un piccolo esempi
 >o (non un codice completo)::
123
124  label = QtGui.QLabel('Testo');
125  label.move(34, 40); # definiamo la posizione ass
 >oluta in pixel con move()
126
127Passiamo all'utilizzo di layout. Ci sono due tipi 
 >di layout: le “boxes” (verticali od orizzontali) e
 > la grid (griglia, o comunemente tabella). Nelle b
 >ox è possibile “impilare” i vari widgets uno dietr
 >o l'altro, verticalmente od orizzontalmente a seco
 >nda del tipo.
128All'interno di un programma si possono usare quant
 >i layout si desiderano, anche annidati (ad esempio
 >, una box verticale dentro una cella di una grigli
 >a), ma bisogna sempre ricordarsi di definirne uno 
 >“genitore” che contenga tutti gli altri, e che sar
 >à impostato come il layout della finestra corrente
 >.
129Andiamo a fare un esempio dell'utilizzo dei due ti
 >pi di box.::
130
131  #!/usr/bin/python
132
133  import sys
134  from PyQt4 import QtGui, QtCore
135
136  class MainWindow(QtGui.QMainWindow):
137        
138        def __init__(self):     
139                QtGui.QMainWindow.__init__(self)
140                self.setWindowTitle('Box example')
 >
141                cWidget = QtGui.QWidget(self)
142                
143                hBox = QtGui.QHBoxLayout()
144                hBox.setSpacing(5)
145                
146                randomLabel = QtGui.QLabel('Enter 
 >the information', cWidget)
147                hBox.addWidget(randomLabel)
148                
149                textEdit = QtGui.QTextEdit(cWidget
 >)
150                if (textEdit.isReadOnly() == True)
 >:
151                        textEdit.setReadOnly(False
 >)
152                hBox.addWidget(textEdit)
153                
154                vBox = QtGui.QVBoxLayout()
155                vBox.setSpacing(2)
156                hBox.addLayout(vBox)
157                
158                button1 = QtGui.QPushButton('Go!',
 > cWidget)
159                vBox.addWidget(button1)
160                button2 = QtGui.QPushButton('Reset
 >', cWidget)
161                vBox.addWidget(button2)
162                
163                cWidget.setLayout(hBox)
164                self.setCentralWidget(cWidget)
165
166  app = QtGui.QApplication(sys.argv)
167  main = MainWindow()
168  main.show()
169  sys.exit(app.exec_())
170
171.. img:: 9
172   :nolink:
173
174Intanto notiamo che sono stati introdotti due nuov
 >i widget: la *label* e la *textEdit*. La *label*, 
 >come potete vedere, è una porzione di testo libero
 >, mentre la *textEdit* permette all'utente di inse
 >rire un testo particolarmente lungo, o al programm
 >a di mostrare dell'output.
175Il metodo *setReadOnly()* permette o vieta all'ute
 >nte di scrivere nella *textEdit*: in realtà il com
 >portamento predefinito è di accettare input dall'u
 >tente, ma in questo caso ce ne “accertiamo” con *i
 >sReadOnly()*.::
176
177                cWidget = QtGui.QWidget(self)
178
179Con questa riga creiamo un widget “astratto”, che 
 >non ha alcuna funzione grafica se non quella di co
 >ntenere tutti gli altri. Infatti è indicato in ogn
 >i widget successivo come il parametro “parent”. A 
 >cosa serve tutto ciò? Per prima cosa, quando in un
 > programma più complesso andremo ad inserire menu 
 >o toolbar, il programma ha bisogno di un solo widg
 >et da riconoscere come centrale: se ne mettiamo un
 >o qualsiasi (ad esempio la *textEdit*), tutti gli 
 >altri non verranno visualizzati. Se omettiamo di s
 >pecificare il widget centrale, non verrà visualizz
 >ato nulla al di là del menu. Il workaround per ciò
 > è appunto creare un widget astratto che contenga 
 >tutti quelli desiderati.
180C'è anche un'altra comodità: se abbiamo bisogno, n
 >el corso del programma, di distruggere/nascondere 
 >il nostro lavoro per sostituirlo ad esempio con de
 >ll'altro output, basterà un semplice::
181
182  cWidget.hide()
183
184per rendere il tutto invisibile. Lo stesso vale al
 > contrario:::
185
186  cWidget.show()
187
188mostrerà tutto di nuovo.
189Un utente si potrebbe chiedere perchè i costruttor
 >i delle due boxes non riportano *cWidget* come par
 >ametro genitore. Non ne abbiamo bisogno, poiché al
 >la fine indichiamo il layout di *cWidget* con il m
 >etodo *setLayout()*. Al contrario, avremmo potuto 
 >dichiarare la hbox come:::
190
191                hBox = QtGui.QHBoxLayout(cWidget)
192
193e poi omettere la chiamata a *setLayout()*, senza 
 >alcun cambiamento nel risultato.
194Ma passiamo alla parte importante, le boxes.::
195
196                hBox = QtGui.QHBoxLayout()
197                hBox.setSpacing(5)
198
199Come facilmente intuibile, ciò serve a creare una 
 >horizontal box (box orizzontale). Il metodo *setSp
 >acing()* è comune a tutti i layout (è presente anc
 >he nelle griglie) per impostare i pixel di spazio 
 >fra i widget appartenenti al layout stesso.::
200
201                randomLabel = QtGui.QLabel('Enter 
 >the information', cWidget)
202                hBox.addWidget(randomLabel) # aggi
 >unge la label alla hbox
203
204Se vogliamo che *randomLabel* sia inserita nella h
 >box, bisogna ovviamente aggiungerla, con il metodo
 > *addWidget()*.::
205
206                hBox.addLayout(vBox)
207
208Se invece vogliamo inserire un altro layout, al su
 >o posto si usa *addLayout()*.::
209
210                cWidget.setLayout(hBox)
211
212La hbox è il layout principale (quello che prima h
 >o definito “genitore”) e quindi va impostato come 
 >centrale con questa chiamata.
213Le box sono comode quando si tratta di inserire in
 > fila pochi widget, ma per grafiche complesse è co
 >nsigliabile usare le grid, o tabelle. Vediamo un e
 >sempio di utilizzo:
214