QGIS är byggt i C++ med Qt. Plugin i QGIS skrivs i Python med PyQt kopplingar till Qt. Du behöver dock inte använda QGIS för att använda Python och PyQt!
I detta inlägg skapar jag ett enkelt GUI med Qt Designer och ett Python program som körs via detta GUI. Det är enklare än du tror!
För det första behöver du Qt Designer och så småningom PyQt. Jag gör allt i Linux, men det borde fungera på i princip samma sätt i såväl Windows som MacOS. Ja själva koden som blir resultatet kan faktiskt köras på alla datorer och operativsystem med Qt installerat!
Qt Designer är ett väldigt enkelt sätt att bygga gränssnitt, vilket inte minst gör det lämpligt för att bygga GUI prototyper, oavsett om man i slutändan skall programmera i Python, C++ eller annat språk.
När man startar Qt Designer så får man först välja en ”mall” för det gränssnitt man skall skapa. I mitt exempel så kommer jag att välja en ”Widget”, som är den enklaste formen av programfönster.
När man skapar ett GUI så är det väldigt enkelt att bara kasta in lite knappar och textfält, men man behöver anstränga sig lite mer än så för att det skall bli bra. Exempelvis så bör man kunna anpassa GUI till olika fönsterstorlekar. Då är ”Layout” bra att använda.
Till att börja med kan man bestämma om hela fönstret skall ha en vertikal eller horisontell layout. Detta görs med knappar i verktygsfältets överkant och innebär att kontroller som läggs till organiseras på detta sätt.
Man kan sedan skapa flera ”under-layouter” i denna med verktyg till vänster, som i sin tur kan vara horisontella, vertikala eller i rutnät. Dessa kan sedan kombineras på olika sätt för att ”organisera” hur kontrollerna placeras relativt varandra även när fönstret ändrar storlek.
Det finns även ”spacers” som kan fylla ut tomrum mellan kontroller och exempelvis se till att en knapp alltid finns i fönstrets nedre högra hörn.
Mitt formulär är inte speciellt komplicerat! Rent funktionellt så består det av en ”line edit” och en ”push button”. Sedan har jag hela fönstret i horisontell layout, med en vertikal layout i mitten. Dessutom använder jag ”spacers” för att alltid se till att text och knapp finns mitt i fönstret.
För att kunna jobba vidare så behöver man även redigera objektens egenskaper. Detta görs i gränssnittet till höger.
Det viktiga nu är att man sätter ett ”objectName” som man kommer ihåg. Jag har även ändrat exempelvis ”text” för min knapp till något passande. ”objectName” för mitt textfält är ”textruta”, och som framgår av bilden ovan heter knappen ”knapp”.
Nu går det att testa gränssnittet genom menyn eller att trycka Ctrl+R.
Svårare än så är det inte att skapa en prototyp för ett GUI! Men man kanske vill att något skall hända också när man trycker på knappen.
Först så behöver gränssnittet sparas till en fil. Jag döper min till ”tryck.ui”.
Detta är en xml-fil som går att öppna i Qt Designer igen och fortsätta att redigera, men den fungerar inte så bra för Python. För detta ändamål så behöver man göra om filen till en *.py fil.
Detta görs med kommandot:
pyuic4 tryck.ui -o tryck.py
Nu använder jag samma utvecklingsmiljö som för QGIS plugin, vilket kanske ställde till det något för mig. Jag behövde ändra i /usr/lib/python2.7/dist-packages/qgis/PyQt/QtCore.py där det står sip.setapi(api, 2) till sip.setapi(api,1). Men sedan fungerade kommandot utan problem. Stöter du på problem så kan du prova att lägga till -d för att aktivera debugg mode för pyic4 kommandot. I mitt fall stod det i princip i klartext vilken fil och vilken rad problemet fanns på, så det var enkelt att ändra.
Den pythonfil som genererats innehåller nu hela gränssnittet som pythonkod, men det kommer inte att hända så mycket om vi kör koden. En del måste ändras först. Och dessa ändringar är hela orsaken till detta inlägg. Jag vill helt enkelt sammanställa det som måste ändras för att jag skall slippa leta så himla mycket nästa gång jag vill göra ett GUI för min Pythonkod.
Till att börja med så skall sys importeras.
imports sys
Detta kan göras direkt efter den import som redan finns.
Sedan kan man hoppa till den class som finns i koden. Där står det object inom parentes, men detta är fel! Klassen skall ärva från QtGui.QWidget och inget annat, så byt helt enkelt ut texten.
class Ui_form(QtGui.QWidget):
För att visa formuläret med alla kontroller så behövs det en funktion till i klassen. Lägg därför till nedanstående kod direkt efter class raden ovan.
def __init__(self): QtGui.QWidget.__init__(self) self.setupUi(self)
För att allt skall köras igång när skriptet körs så behövs något som initierar klassen. Lägg därför till följande kod sist i filen.
if __name__ in '__main__': app = QtGui.QApplication(sys.argv) ex = Ui_form() ex.show() sys.exit(app.exec_())
Kontrollera även att exempelvis ”Ui_form” heter samma sak överallt i koden. Denna text beror nämligen på vad du döpt ditt formulär till i Qt Designer. Observera även att den sista koden skall ha samma indrag som class tidigare, medan def har samma indrag som övriga def.
Kör du nu koden så kommer gränssnittet att visas, men det händer fortfarande ingenting när du klickar på knappen.
För att något skall hända så behöver vi fånga en händelse. Detta görs genom att lägga till en rad under raden som börjar med self.knapp.setText.
self.knapp.clicked.connect(self.skrivut)
Sedan behövs den funktion som kommandot ovan anropar också.
def skrivut(self): self.textruta.setText("Du klickade")
När nu Pythonkoden körs med python tryck.py så startas gränssnittet och det händer något när man klickar på knappen!
Nu går det att göra koden många gånger mer komplicerad men grunden för att hantera händelser i GUI görs på motsvarande sätt. Sedan kan man självklart använda externa moduler för att exempelvis göra beräkningar eller kommunicera med inkopplade tillbehör.
Sammanfattning
Qt Designer är inte speciellt svårare att använda än Power Point eller Excel och ett väldigt kraftfullt verktyg för att bygga GUI för olika tillämpningar. Detta är inte minst användbart för att snabbt skapa prototyper i olika sammanhang.
Det finns massor med templates och stilar man kan använda sig av och om man använder Qt5 istället för som här Qt4 så får man ännu flera möjligheter till stilar.
Det är sedan inte speciellt svårt att koppla Pythonkod till gränssnittet. Skillnaden mot att använda C++ är att man exekverar koden långsammare samt att man är begränsad till den funktionalitet som finns i PyQt. Om man däremot inte vill använda mer än själva GUI så är detta knappast en begränsning.