Eccoci giunti al secondo appuntamento del percorso che ci porterà a costruire un basilare feed reader. Nella precedente puntata abbiamo visto come fare il parsing di un feed RSS attraverso l’utilizzo della libreria Universal Feed Parser. Oggi inizieremo a vedere le basi per la costruzione di una semplice interfaccia grafica per visualizzare i dati ottenuti. Le librerie grafiche utilizzate saranno le Qt4. Essendo Qt un framework nativo C++ e dovendolo integrare nel nostro progetto python utilizzeremo binding forniti dalla Riverbank computing, le PyQt.
Chi utilizza una distribuzione GNU/Linux debian based (per esempio Ubuntu) dovrà installare i pacchetti:
python-qt4
qt4-designer
Gli installer per Windows e MacOSX possono essere scaricati dal sito della Riverbank Computing.
DISEGNIAMO L’INTERFACCIA
Per prima cosa apriamo Qt Designer (programma per la costruzione di interfacce) e selezioniamo Main Window tra i template disponibili. Quello che ci troveremo avanti sarà una tipica finestra principale composta da un widget centrale, una barra dei menu ed una barra di stato.
Per semplicità utilizzeremo un widget per la visualizzazione degli elementi del feed (QTreeWidget). In generale è sempre consigliabile utilizzare le view rispetto ai widget essendo le prime estremamente più flessibili. L’unico costo della prima soluzione è una logica implementativa più complessa che richiede la comprensione del pattern Model View Controller che esula dagli scopi di questa serie di post.
Per aggiungere il QTreeWidget è sufficiente trascinarlo dalla colonna di sinistra (Widget Box) all’interno della Main Window. Fatto questo possiamo modificare il numero di colonne del TreeWidget semplicemente facendo doppio click sopra al widget appena inserito.
Nello specifico inseriremo i campi “titolo”, “autore” e “commenti”. L’ultima cosa rimasta da fare prima di mettere da parte il designer è selezionare un layout. In questo caso selezionare un layout verticale od orizzontale è assolutamente indifferente visto che abbiamo inserito un solo widget.
Fatto questo possiamo salvare il file all’interno della cartella dei sorgenti del programma (mainwindow.ui).
COMPILIAMO L’INTERFACCIA
Il file salvato non è nient’altro che un file XML che contiene la descrizione dell’interfaccia. Tale file dovrà essere processato con il tool pyuic per generare automaticamente il codice python necessario alla creazione dell’interfaccia descritta.
Per compiere l’operazione è necessario invocare il tool da riga di comando:
pyuic4 ./mainwindow.ui -o ./mainwindowUi.py
Il file mainwindowUi.py non va mai modificato manualmente poichè verrà sovrascritto ad ogni modifica e ricompilazione del file .ui.
Compiuto questo passo abbiamo tutto il necessario per costruire la nostra applicazione grafica.
SCRIVIAMO IL CODICE DELL’APPLICAZIONE
Per avere una visione complessiva potete osservare il codice sorgente completo.
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys # Import Qt modules from PyQt4.QtCore import * from PyQt4.QtGui import * # Import pyuic4 compiled GUI from mainwindowUi import Ui_MainWindow import feedparser class Main(QMainWindow): def __init__(self): QMainWindow.__init__(self) # Setup pyuic generated code self.ui = Ui_MainWindow() self.ui.setupUi(self) ad = feedparser.parse("https://www.appuntidigitali.it/feed") #Populate TreeWiget with elements for entry in ad.entries: item = QTreeWidgetItem([entry.title, entry.author, entry.slash_comments]) self.ui.treeWidget.addTopLevelItem(item) if __name__ == "__main__": app = QApplication(sys.argv) window=Main() window.show() sys.exit(app.exec_())
Questo file (che io ho chiamato adreader.py) è il file principale del nostro progetto. Se avete qualche nome più evocativo (magari con una i davanti :P) potete semplicemente consigliarlo nei commenti.
Analizziamo adesso i punti salienti:
#!/usr/bin/env python # -*- coding: utf-8 -*-
La prima riga non è altro che uno Shebang che serve ad indicare al sistema operativo con quale interprete utilizzare per lo script lanciato. Con questo piccolo accorgimento è possibile lanciare il programma senza far riferimento in maniera esplicita all’interprete python ma richiamandolo come eseguibile. La seconda riga serve a dichiarare la codifica del file sorgente.
Sospetto che queste due righe non servano assolutamente a niente in ambiente windows poichè la prima è legata ad una caratteristica tipica dei sistemi unix e la codifica standard in casa MS non è utf-8.
Sotto segnalazione dell’attento Carlosh aggiungo che in realtà la dichiarazione della codifica è necessaria anche sotto windows per non incappare in errori di sintassi nel caso utilizzassimo caratteri accentati.
import sys # Import Qt modules from PyQt4.QtCore import * from PyQt4.QtGui import * # Import pyuic4 compiled GUI from mainwindowUi import Ui_MainWindow import feedparser
Subito sotto vengono importati i vari moduli utilizzati all’interno del programma. Alla riga 6 viene importata la classe Ui_MainWindow ottenuta dalla compilazione del file ui con il tool pyuic4 descritto in precedenza.
Finita la parte di importazione dei moduli possiamo vedere la definizione della classe Main.
class Main(QMainWindow): def __init__(self): QMainWindow.__init__(self) # Setup pyuic generated code self.ui = Ui_MainWindow() self.ui.setupUi(self)
La nostra classe Main è una classe figlia di QMainWindow delle Qt. Come prima cosa viene sovrascritto il costruttore (metodo __init__). All’interno del costruttore della nostra classe Main deve essere richiamato il costruttore di QMainWindow (classe genitrice) a cui passiamo il riferimento dell’attuale oggetto Main istanziato (self).
Subito dopo si eseguono due passi per l’integrazione del codice generato da pyuic nel nostro Main. Non spiegherò cosa avviene nello specifico ma se andate a leggere il codice del file prodotto da pyuic (mainwindowUi.py) potete farvi un idea più approfondita. Quello che basta sapere è che adesso possiamo accedere a tutti i widget composti in precedenza con il designer semplicemente riferendoci all’oggetto ui della classe Main.
A questo punto rimane solo da fare il parsing del feed e popolare il treeWidget con QTreeWidgetItem ad-hoc.
#Populate TreeWiget with elements for entry in ad.entries: item = QTreeWidgetItem([entry.title, entry.author, entry.slash_comments]) self.ui.treeWidget.addTopLevelItem(item)
Il codice è assolutamente triviale e non merita particolari spiegazioni.
Quello che rimane è il main del nostro programma:
if __name__ == "__main__":
La variabile __name__ in python contiene il namespace. Se un file sorgente viene importato come modulo il suo namespace corrisponde al nome del file. Se invece il file viene invocato direttamente il suo namespace sarà uguale a “__main__”.
L’istruzione condizionale fa in modo che la porzione di codice sottostante venga eseguita solo in caso di invocazione diretta del file e non nel caso di importazione.
app = QApplication(sys.argv) window=Main() window.show() sys.exit(app.exec_())
Nelle quattro righe successive non si fa altro che creare una QApplication (sempre necessaria per le applicazioni che utilizzano le Qt), istanziare la classe Main appena scritta, mostrare a schermo la finestra principale ed attendere la chiusura dell’applicazione.
Con questi semplicissimi passi avete visto come si può creare in maniera rapida una piccola applicazione grafica. Nella prossima (e credo ultima) puntata vedremo come gestire gli eventi e come visualizzare un post in una webView.