| app = QtGui.QApplication(sys.argv) | | app = QtGui.QApplication(sys.argv) |
| main = MainWindow() | | main = MainWindow() |
| main.show() | | main.show() |
| sys.exit(app.exec_()) | | sys.exit(app.exec_()) |
| | | |
t | | t | .. img:: 8
|
| | | :nolink:
|
| | |
|
| | | Le quattro righe “nuove” sono::
|
| | |
|
| | | button = QtGui.QPushButton('Quit') |
| | | ;
|
| | | button.setFont(QtGui.QFont("Times" |
| | | , 10, QtGui.QFont.Bold));
|
| | | self.connect(button, QtCore.SIGNAL |
| | | ('clicked()'), QtCore.SLOT('close()'));
|
| | |
|
| | | self.setCentralWidget(button);
|
| | |
|
| | | Con la prima, creiamo un nuovo pulsante con il nom |
| | | e Quit. La definizione completa di questo costrutt |
| | | ore è:
|
| | |
|
| | | *__init__ (self, QIcon icon, QString text, QWidget |
| | | parent = None)*
|
| | |
|
| | | Come 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.
|
| | | *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.
|
| | | Per 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.
|
| | |
|
| | | Segnali e slot
|
| | | ###############
|
| | |
|
| | | La 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).
|
| | | I 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.
|
| | | Altri 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*.
|
| | |
|
| | | È possibile anche emettere un particolare segnale |
| | | utilizzando *emit*.
|
| | |
|
| | | Layout
|
| | | #######
|
| | |
|
| | | Passiamo all'inserimento di più widgets.
|
| | | Il posizionamento di più widgets all'interno della |
| | | finestra si può realizzare in due modi: tramite i |
| | | l cosiddetto posizionamento assoluto, o definendo |
| | | dei layout.
|
| | |
|
| | | Il 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.
|
| | | Tuttavia, se volete usarlo, ecco un piccolo esempi |
| | | o (non un codice completo)::
|
| | |
|
| | | label = QtGui.QLabel('Testo');
|
| | | label.move(34, 40); # definiamo la posizione ass |
| | | oluta in pixel con move()
|
| | |
|
| | | Passiamo 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.
|
| | | All'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 |
| | | .
|
| | | Andiamo a fare un esempio dell'utilizzo dei due ti |
| | | pi di box.::
|
| | |
|
| | | #!/usr/bin/python
|
| | |
|
| | | import sys
|
| | | from PyQt4 import QtGui, QtCore
|
| | |
|
| | | class MainWindow(QtGui.QMainWindow):
|
| | |
|
| | | def __init__(self):
|
| | | QtGui.QMainWindow.__init__(self)
|
| | | self.setWindowTitle('Box example') |
| | |
|
| | | cWidget = QtGui.QWidget(self)
|
| | |
|
| | | hBox = QtGui.QHBoxLayout()
|
| | | hBox.setSpacing(5)
|
| | |
|
| | | randomLabel = QtGui.QLabel('Enter |
| | | the information', cWidget)
|
| | | hBox.addWidget(randomLabel)
|
| | |
|
| | | textEdit = QtGui.QTextEdit(cWidget |
| | | )
|
| | | if (textEdit.isReadOnly() == True) |
| | | :
|
| | | textEdit.setReadOnly(False |
| | | )
|
| | | hBox.addWidget(textEdit)
|
| | |
|
| | | vBox = QtGui.QVBoxLayout()
|
| | | vBox.setSpacing(2)
|
| | | hBox.addLayout(vBox)
|
| | |
|
| | | button1 = QtGui.QPushButton('Go!', |
| | | cWidget)
|
| | | vBox.addWidget(button1)
|
| | | button2 = QtGui.QPushButton('Reset |
| | | ', cWidget)
|
| | | vBox.addWidget(button2)
|
| | |
|
| | | cWidget.setLayout(hBox)
|
| | | self.setCentralWidget(cWidget)
|
| | |
|
| | | app = QtGui.QApplication(sys.argv)
|
| | | main = MainWindow()
|
| | | main.show()
|
| | | sys.exit(app.exec_())
|
| | |
|
| | | .. img:: 9
|
| | | :nolink:
|
| | |
|
| | | Intanto 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.
|
| | | Il 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()*.::
|
| | |
|
| | | cWidget = QtGui.QWidget(self)
|
| | |
|
| | | Con 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.
|
| | | C'è 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::
|
| | |
|
| | | cWidget.hide()
|
| | |
|
| | | per rendere il tutto invisibile. Lo stesso vale al |
| | | contrario:::
|
| | |
|
| | | cWidget.show()
|
| | |
|
| | | mostrerà tutto di nuovo.
|
| | | Un 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:::
|
| | |
|
| | | hBox = QtGui.QHBoxLayout(cWidget)
|
| | |
|
| | | e poi omettere la chiamata a *setLayout()*, senza |
| | | alcun cambiamento nel risultato.
|
| | | Ma passiamo alla parte importante, le boxes.::
|
| | |
|
| | | hBox = QtGui.QHBoxLayout()
|
| | | hBox.setSpacing(5)
|
| | |
|
| | | Come 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.::
|
| | |
|
| | | randomLabel = QtGui.QLabel('Enter |
| | | the information', cWidget)
|
| | | hBox.addWidget(randomLabel) # aggi |
| | | unge la label alla hbox
|
| | |
|
| | | Se vogliamo che *randomLabel* sia inserita nella h |
| | | box, bisogna ovviamente aggiungerla, con il metodo |
| | | *addWidget()*.::
|
| | |
|
| | | hBox.addLayout(vBox)
|
| | |
|
| | | Se invece vogliamo inserire un altro layout, al su |
| | | o posto si usa *addLayout()*.::
|
| | |
|
| | | cWidget.setLayout(hBox)
|
| | |
|
| | | La hbox è il layout principale (quello che prima h |
| | | o definito “genitore”) e quindi va impostato come |
| | | centrale con questa chiamata.
|
| | | Le 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:
|
| | |
|