PyQt5-handledning med exempel: Skapa Python GUI:er med Qt
⚡ Smart sammanfattning
PyQt är en Python bindning för plattformsoberoende Qt-widgetverktygslådan, vilket låter utvecklare bygga inbyggda skrivbordsgränssnitt. Den omfattar mer än sexhundra C++ klasser som täcker fönster, knappar, layouter, signaler, platser och teman för Windows, macOSoch Linux.
Avsnitten nedan tar dig från grunderna i PyQt till installation, kärnwidgetar, layouter och teman med körbara exempel.
Vad är PyQt?
PyQt är en Python bindning av widget-toolkit med öppen källkod Qt, som också fungerar som ett plattformsoberoende applikationsutvecklingsramverk. Qt är ett populärt C++ ramverk för att skriva GUI-applikationer för alla större stationära, mobila och inbäddade plattformar (det stöder Linux, Windows, macOS, Android, iOS, Raspberry Pi och mer).
PyQt är fri programvara utvecklad och underhållen av Riverbank Computing, ett företag baserat i England, medan Qt är utvecklad av ett finskt företag som heter The Qt Company.
Funktioner i PyQt
Här är viktiga funktioner i PyQt:
PyQt består av mer än sexhundra klasser som täcker en rad funktioner som:
- Grafiska användargränssnitt
- SQL Databaser
- Webbverktygssatser
- XML-bearbetning
- nätverk
Dessa funktioner kan kombineras för att skapa avancerade användargränssnitt såväl som fristående applikationer. Många stora företag inom alla branscher använder Qt. Några exempel är LG, Mercedes, AMD, Panasonic och Harman.
PyQt-versioner
PyQt finns i två utgåvor, PyQt4 och PyQt5. PyQt4 tillhandahåller kod för att binda 4.x- och 5.x-versionerna av Qt-ramverket medan PyQt5 endast tillhandahåller en bindning för 5.x-versionerna. Som ett resultat är PyQt5 inte bakåtkompatibel med de föråldrade modulerna i den äldre versionen. I denna PyQt GUI-handledning kommer PyQt5 att användas för demonstration av exempel. Förutom dessa två versioner tillhandahåller Riverbank Computing även PyQt3D—den Python bindningar för Qt3D-ramverket. Qt3D är ett applikationsramverk som används för att skapa realtidssimuleringssystem med 2D/3D-rendering.
Hur man installerar PyQt5
I denna PyQt5-handledning kommer vi att se de två sätten att installera PyQt:
- Använder hjulfiler
- Bygga och installera från källan
Qt (uttalas söt) är ett komplext system, och PyQt-kodbasen innehåller kompilerade C++ och Python kod under huven. Som ett resultat är det en komplicerad process att bygga och installera den från källkoden jämfört med andra Python bibliotek. Du kan dock enkelt installera PyQt5 med hjälp av hjul.
Montering med hjul
Hjul är den nya standarden Python förpacknings- och distributionsformat. Ett hjul är helt enkelt ett ZIP-arkiv med ett speciellt namn och .WHL filtillägg. Hjul kan installeras med pip (Pythons pakethanterare), som ingår som standard i de senaste versionerna av Python.
Så, om du har Python 3.4 eller senare installerat, du har redan pip. Om du däremot använder en äldre version av Python, måste du ladda ner och installera pip innan du fortsätter. Du kan söka efter instruktioner på den här länken: https://pypi.org/project/pip/.
För att installera PyQt5:
Steg 1) Öppna kommandotolken.
Öppna kommandotolken eller PowerShell i din Windows maskin.
Steg 2) Skriv in följande.
pip install PyQt5
Steg 3) Lyckad installation.
Det här steget i denna PyQt5-handledning kommer att ladda ner PyQt5 whl-paketet (ca 50 MB) och installera det på ditt system.
Alternativt kan du också ladda ner en Windows binär för versionen av Python installerad på din dator.
När det är klart, fortsätt till nästa avsnitt i denna PyQt5-handledning för att skriva din första GUI-app.
Grundläggande PyQt Concepts och program
Nu när du har installerat PyQt5 på din dator är du redo att skriva Python GUI-applikationer.
Låt oss börja med en enkel app i den här PyQt5-handledningen som visar ett tomt fönster på skärmen.
Tänd igång din Python IDLE och skriv in följande:
Program 1
import sys from PyQt5.QtWidgets import QApplication, QWidget if __name__ == "__main__": app = QApplication(sys.argv) w = QWidget() w.resize(300,300) w.setWindowTitle("Guru99") w.show() sys.exit(app.exec_())
Spara den som app.py (namnet spelar ingen roll) och tryck på F5 för att köra programmet. Alternativt kan du bara dubbelklicka på din sparade fil för att starta programmet. Om du har gjort allt rätt öppnas ett nytt fönster med titeln. Guru99 som visas nedan.
Toppen! Det fungerar. Det är inte mycket, men det räcker för att förstå grunderna. Nu i den här PyQt-handledningen ska vi se i detalj vad varje rad i ditt program gör.
from PyQt5.QtWidgets import QApplication, QWidget
Denna sats importerar alla moduler du behöver för att skapa ett GUI till det aktuella namnområdet. QtWidgets-modulen innehåller alla större widgets som du kommer att använda i detta Python Qt handledning.
app = QApplication(sys.argv)
Här skapar du ett objekt av klassen QApplication. Detta steg är en nödvändighet för PyQt5; varje UI-app måste skapa en instans av QApplication, som en slags ingångspunkt till appen. Om du inte skapar det kommer fel att visas.
sys.argv är listan över kommandoradsparametrar som du kan skicka till programmet när du startar det genom skalet eller när du automatiserar gränssnittet.
I det här PyQt5-exemplet skickade du inga argument till QApplication. Därför kan du även ersätta det med koden nedan och slipper importera sys-modulen.
app = QApplication([])
w = QWidget()
Därefter gör vi ett objekt av klassen QWidget. QWidget är basklassen för alla UI-objekt i Qt, och praktiskt taget allt du ser i en app är en widget. Det inkluderar dialoger, texter, knappar, staplar och så vidare. Funktionen som gör att du kan designa komplexa användargränssnitt är att widgetarna kan kapslas, dvs du kan ha en widget inuti en widget, som finns i ännu en widget. Du kommer att se detta i aktion i nästa avsnitt.
w.resize(300,300)
Resize-metoden för QWidget-klassen låter dig ställa in måtten på vilken widget som helst. I det här fallet har du ändrat storleken på fönstret till 300px med 300px.
Här bör du komma ihåg att widgetar kan kapslas tillsammans; den yttersta widgeten (dvs. widgeten utan förälder) kallas ett fönster.
w.setWindowTitle("Guru99")
Metoden setWindowTitle() låter dig skicka en sträng som ett argument som ställer in fönstrets titel till den sträng du skickar. I PyQt5-exemplet kommer titelfältet att visas Guru99.
w.show()
show() visar helt enkelt widgeten på skärmen.
sys.exit(app.exec_())
Metoden app.exec_() startar Qt/C++ händelseslinga. Som ni vet är PyQt till stor del inskrivet C++ och använder händelseloopmekanismen för att implementera parallell exekvering. app.exec_() överför kontrollen till Qt, som endast avslutar applikationen när användaren stänger den från det grafiska gränssnittet. Det är därför ctrl+c inte avslutar applikationen som i andra Python program. Eftersom Qt har kontroll över appen, Python Händelser bearbetas inte om vi inte konfigurerar dem inuti applikationen. Observera också att exec-metoden har ett understreck i namnet; detta beror på att exec() redan var ett nyckelord i Python och understrecket löser namngivningskonflikten.
Bortom tomma fönster
I föregående avsnitt såg du hur man skapar en enkel widget i Qt. Nu är det dags att skapa några mer komplicerade gränssnitt som användarna verkligen kan interagera med. Återigen, starta din IDLE och skriv följande.
import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QMessageBox def dialog(): mbox = QMessageBox() mbox.setText("Your allegiance has been noted") mbox.setDetailedText("You are now a disciple and subject of the all-knowing Guru") mbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) mbox.exec_() if __name__ == "__main__": app = QApplication(sys.argv) w = QWidget() w.resize(300,300) w.setWindowTitle("Guru99") label = QLabel(w) label.setText("Behold the Guru, Guru99") label.move(100,130) label.show() btn = QPushButton(w) btn.setText('Beheld') btn.move(110,150) btn.show() btn.clicked.connect(dialog) w.show() sys.exit(app.exec_())
Spara filen som appone.py eller något annat du gillar och tryck på F5 för att köra programmet. Om du inte har gjort några misstag, IDLE kommer att öppna ett nytt fönster med lite text och en knapp som visas nedan.
- När du klickar på knappen i det första fönstret öppnas en ny meddelanderuta med texten du skrivit.
- Du kan nu klicka på knappen Dölj detaljer/Visa detaljer för att växla synligheten för ytterligare text.
Som du kan se, eftersom vi inte hade angett någon fönstertitel i meddelanderutan, tillhandahölls en standardtitel av Python själv.
Nu när det fungerar, låt oss ta en titt på den extra kod som du har lagt till i det föregående PyQt5-exemplet.
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QMessageBox
Detta importerar några fler widgets som du har använt i PyQt5-exemplen, nämligen QLabel, QPushButton och QMessageBox.
def dialog(): mbox = QMessageBox() mbox.setText("Your allegiance has been noted") mbox.setDetailedText("You are now a disciple and subject of the all-knowing Guru") mbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) mbox.exec_()
Här har du definierat en metod med namnet dialog som skapar en meddelandebox-widget och ställer in lite text till knapparna och andra fält.
Dialogmetoden anropas från programmets huvudblock när en knapp trycks in i en specifik widget (i detta fall btn-tryckknappen). Klickhändelsen som utlöses på den knappen gör att den här funktionen körs. En sådan funktion kallas slot i Qt, och du kommer att lära dig mer om signaler och spelautomater i de kommande styckena.
if __name__ == "__main__": app = QApplication(sys.argv) w = QWidget() w.resize(300,300) w.setWindowTitle("Guru99")
Detta är appens huvuddel och, precis som i föregående exempel, börjar du med att skapa en instans av QApplication följt av en enkel widget, dvs. en instans av QWidget.
label = QLabel(w)
btn = QPushButton(w)
Du har lagt till två nya widgets i denna applikation: QLabel och QPushButton. QLabel används för att skriva ut icke-redigerbar text eller platshållare inuti en widget, medan QPushButton används för att skapa en klickbar knapp.
Det kritiska att lägga märke till här är att när du skapar etikett- och btn-objekten skickar du fönsterobjektet (w) till konstruktörerna av QLabel och QPushButton. Så här fungerar kapsling i PyQt5. För att skapa en widget i en annan widget skickar du referensen för den överordnade widgeten till barnets konstruktor.
label.move(100,130) btn.move(110,150)
move() används för att ställa in positionen för en widget i förhållande till dess överordnade widget. I det första fallet kommer etiketten att flyttas 100px från vänster och 130px från toppen av fönstret.
På samma sätt kommer knappen att placeras 110px från vänster och 150px från toppen av fönstret. Detta exempel är ett grovt sätt att uppnå layouter och används vanligtvis inte i produktionen; den ingår bara här i lärande syfte. Qt stöder olika layouter som du kommer att se i detalj i de kommande avsnitten av denna PyQt-handledning.
btn.clicked.connect(dialog)
Slutligen är detta ett exempel på signaler och platser i Qt. I GUI-baserade applikationer exekveras funktioner baserat på de åtgärder som utförs av användaren, som att hålla muspekaren över ett element eller klicka på en knapp. Dessa åtgärder kallas händelser. Kom ihåg att metoden app.exec_() överför kontrollen till Qt händelse slinga. Detta är vad händelseslingan är till för: att lyssna efter händelser och utföra åtgärder som svar.
Närhelst en händelse inträffar, som att en användare klickar på en knapp, höjer motsvarande Qt-widget en signal. Dessa signaler kan kopplas till Python funktioner (som dialogfunktionen i detta exempel) så att funktionen exekveras när en signal triggas. Dessa funktioner kallas spelautomater på Qt-språk.
Därefter är den grundläggande syntaxen för att utlösa en slotfunktion som svar på signalen från en händelse följande:
widget.signal.connect(slot)
Detta innebär att närhelst en signal utlöses av en widget, den anslutna slits funktionen kommer att köras. Sammanfattningsvis används signaler och slots av Qt för att kommunicera mellan objekt och underlätta återanvändbarhet och interaktivitet av komponenter.
Nu när du vet hur man kapslar widgets och implementerar interaktioner med hjälp av signaler och slots, här är en lista med användbara widgets och andra klasser som du kan använda i dina PyQt-appar.
Komponenter och widgets
Det finns ett stort antal widgets tillgängliga i PyQt för att skapa GUI-appar. Men med PyQt5 har det skett en omblandning av klasser till olika moduler och revisioner i licenserna.
Därför är det avgörande att ha en översikt över PyQt5:s struktur. I det här avsnittet får du se hur PyQt5 är organiserat internt och lära dig om de olika modulerna, biblioteken och API-klasserna som tillhandahålls av PyQt5.
PyQt5 Katalogstruktur
Dessa är de grundläggande modulerna som används av Pythons Qt-bindning, specifikt PyQt5.
- QtDen kombinerar alla klasser/moduler som nämns nedan till en enda modul. Den ökar avsevärt minnesanvändningen för applikationen. Det är dock enklare att hantera ramverket genom att bara importera en modul.
- QtCore: Innehåller de icke-grafiska kärnklasserna som används av andra moduler. Det är här Qt-händelseloopen, signaler och slot-anslutning etc. implementeras.
- QtWidgetsInnehåller de flesta widgets som finns i PyQt5.
- QtGui: Innehåller GUI-komponenter och utökar QtCore-modulen.
- QtNetwork: Innehåller klasser som används för att implementera nätverksprogrammering genom Qt. Den stöder TCP-servrar, TCP-sockets, UDP-sockets, SSL-hantering, nätverkssessioner och DNS-sökningar.
- QtMultimedia: tillhandahåller multimediafunktionalitet på låg nivå.
- QtSql: implementerar databasintegration för SQL-databaser. Stöder ODBC, MySQL, Oracle, SQLiteoch PostgreSQL.
PyQt5-widgets
Här är en lista över de mest använda widgetarna i PyQt5:
- QLineEdit: Detta är ett inmatningsfält som tillåter en textrad att skrivas in av användaren.
line = QLineEdit()
- QRadioButtonDetta är ett inmatningsfält med en valbar knapp, liknande radioknapparna i HTML.
rad = QRadioButton("button title") rad.setChecked(True) #to select the button by default.
- QComboBox: Den används för att visa en rullgardinsmeny med en lista över valbara objekt.
drop = QComboBox(w) drop.addItems(["item one", "item two", "item three"])
- QCheckBox: Visar en valbar fyrkantig ruta framför etiketten som är markerad om den är markerad, liknande alternativknappar.
check = QCheckBox("button title")
- QMenuBarDen visar en horisontell menyrad högst upp i ett fönster. Du kan bara lägga till objekt av QMenu-klassen i den här raden. Dessa QMenu-objekt kan vidare innehålla strängar, QAction-objekt eller andra QMenu-objekt.
- QToolBar: Det är en horisontell stapel eller ruta som kan flyttas inom fönstret. Den kan innehålla knappar och andra widgets.
- QTabDen används för att dela upp innehållet i ett fönster i flera sidor som kan nås via olika flikar högst upp i widgeten. Den består av två sektioner: flikfältet och fliksidan.
- QScrollBarDen används för att skapa rullningslister som låter användaren rulla upp och ner i ett fönster. Den består av ett rörligt reglage, ett reglage track och två knappar för att rulla reglaget uppåt eller nedåt.
scroll = QScrollBar()
- QSplitter: Splittrar används för att separera innehållet i ett fönster så att widgetarna grupperas korrekt och inte verkar röriga. QSplitter är en av de primära layouthanterarna som finns i PyQt5 och används för att dela upp innehållet både horisontellt och vertikalt.
- QDockEn dockningswidget är ett underfönster med två egenskaper: den kan flyttas inom huvudfönstret och den kan dockas utanför det överordnade fönstret till en annan plats på skärmen.
Layouter och teman
I de tidigare PyQt5-exemplen har du bara använt metoderna move() och resize() för att ställa in positionerna för widgets i ditt GUI.
PyQt har dock en robust layouthanteringsmotor som kan användas för att skapa avancerade användargränssnitt för applikationer. I det här avsnittet kommer du att lära dig om två viktiga klasser som används i Qt för att skapa och hantera layouter.
- QBoxLayout
- QGridLayout
QBoxLayout
QBoxLayout används för att justera layoutens underordnade widgets i en horisontell eller vertikal rad. De två intresseklasserna som ärver från QBoxLayouten är:
- QHBoxLayout: används för att rada de underordnade widgetarna horisontellt.
- QVBoxLayout: används för att rada de underordnade widgetarna vertikalt.
Till exempel är det så här tre knappar är i linje med QHBoxLayouten kommer att se ut.
import sys from PyQt5.QtWidgets import * if __name__ == "__main__": app = QApplication([]) w = QWidget() w.setWindowTitle("Musketeers") btn1 = QPushButton("Athos") btn2 = QPushButton("Porthos") btn3 = QPushButton("Aramis") hbox = QHBoxLayout(w) hbox.addWidget(btn1) hbox.addWidget(btn2) hbox.addWidget(btn3) w.show() sys.exit(app.exec_())
Och så här kommer de att se ut i QVBoxLayout.
import sys from PyQt5.QtWidgets import * if __name__ == "__main__": app = QApplication([]) w = QWidget() w.setWindowTitle("Musketeers") btn1 = QPushButton("Athos") btn2 = QPushButton("Porthos") btn3 = QPushButton("Aramis") vb = QVBoxLayout(w) vb.addWidget(btn1) vb.addWidget(btn2) vb.addWidget(btn3) w.show() sys.exit(app.exec_())
Den enda funktionen som behöver någon förklaring vid det här laget är metoden addWidget(). Den används för att infoga widgets i HBox eller VBox layout. Det används också i andra layouter där det tar ett annat antal parametrar som du kommer att se i nästa avsnitt. Widgetarna kommer att visas i layouten i den ordning som du infogar dem.
QGridLayout
QGridLayout används för att skapa gränssnitt där widgetarna är upplagda i form av ett rutnät (som en matris eller 2D-array). För att infoga element i en rutnätslayout kan du använda matrisrepresentationen för att definiera antalet rader och kolumner i rutnätet samt positionen för dessa element.
Till exempel, för att skapa ett 3*3 rutnät (dvs ett rutnät med tre rader och tre kolumner), skriver du följande kod:
Import sys from PyQt5.QtWidgets import * if __name__ == "__main__": app = QApplication([]) w = QWidget() grid = QGridLayout(w) for i in range(3): for j in range(3): grid.addWidget(QPushButton("Button"),i,j) w.show() sys.exit(app.exec_())
Detta kommer att vara utgången:
Metoden addWidget() i rutnätslayouten tar dessa argument:
- Widgetobjektet som du vill lägga till i rutnätet
- Objektets x-koordinat
- Objektets y-koordinat
- Radspannet (standard = 0)
- Kolumnspannet (standard = 0)
För att förstå det bättre kan du manuellt infoga varje widget enligt nedan.
import sys from PyQt5.QtWidgets import * if __name__ == "__main__": app = QApplication([]) w = QWidget() grid = QGridLayout(w) grid.addWidget(QPushButton("Button one"),0,0) grid.addWidget(QPushButton("Button two"),0,1) grid.addWidget(QPushButton("Button three"),1,0) grid.addWidget(QPushButton("Button four"),1,1) w.show() sys.exit(app.exec_())
Så här kommer rutnätet att se ut:
Du kan också skicka parametrarna rowspan och colspan till addWidget() för att spänna över mer än en rad eller kolumn.
Till exempel,
grid.addWidget(QPushButton("Button five"),2,0,1,0)
Detta skapar en knapp som sträcker sig över båda kolumnerna.
teman
PyQt5 kommer med några inbyggda teman som du kan använda i dina appar. De setStyle() metod som anropas på QApplication-instansen används för att ställa in ett särskilt tema för din applikation.
Om du till exempel lägger till följande kodrad ändras programmets tema från standard till Fusion.
app.setStyle("Fusion")
Så här kommer det föregående exemplet att se ut i Fusion-temat.
En annan användbar funktion för att temange dina appar är metoden setPalette(). Här är koden för att ändra färgen på olika widgetar med hjälp av setPalette().
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import * from PyQt5.QtGui import QPalette if __name__ == "__main__": app = QApplication([]) app.setStyle("Fusion") qp = QPalette() qp.setColor(QPalette.ButtonText, Qt.black) qp.setColor(QPalette.Window, Qt.black) qp.setColor(QPalette.Button, Qt.gray) app.setPalette(qp) w = QWidget() grid = QGridLayout(w) grid.addWidget(QPushButton("Button one"),0,0) grid.addWidget(QPushButton("Button two"),0,1) grid.addWidget(QPushButton("Button three"),1,0) grid.addWidget(QPushButton("Button four"),1,1) w.show() sys.exit(app.exec_())
Här är resultatet.
För att använda metoden setPalette() måste du först definiera en palett. Detta görs genom att skapa ett objekt av klassen QPalette.
qp = QPalette()
Observera att QPalette-klassen tillhör QtGui-modulen och du måste importera den för att detta ska fungera. När du har skapat QPalette-objektet använder du metoden setColor() för att skicka namnet på en widget vars färg du vill ändra och den färg du vill ha inställd.
qp.setColor(QPalette.Window, Qt.black)
Detta ändrar fönstrets färg till svart. När du har definierat ditt färgschema använder du funktionen setPalette() för att tillämpa paletten på ditt program.
app.setPalette(qp)
Det är allt du behöver göra om du vill skapa några grundläggande teman för din app. PyQt låter dig också använda stilmallar för att definiera utseendet på dina widgets. Om du är bekant med CSS kan du enkelt definiera avancerade stilar för din app med hjälp av Qt Style Sheets.













