Obsah
1. Tvorba GUI v Pythonu s využitím frameworku PySide: grafické operace používající třídu QPainter
2. Základní operace podporované třídou QPainter
3. Praktický postup při vykreslování
4. První demonstrační příklad: použití metod QPainter.begin a QPainter.end
5. Použití „chytrého“ konstruktoru objektu typu QPainter
6. Druhý demonstrační příklad: použití „chytrého“ konstruktoru objektu typu QPainter
7. Modifikace barvy a šířky pera použitého při vykreslování
8. Názvy barev s paletě knihovny PySide
9. Třetí demonstrační příklad: modifikace barvy a šířky pera
10. Čtvrtý demonstrační příklad: použití antialiasingu při vykreslování
11. Čárkované a čerchované úsečky
12. Pátý demonstrační příklad: kresba čárkovaných a čerchovaných úseček
13. Použití štětců při kreslení vyplněných grafických objektů
14. Šestý demonstrační příklad: vzorník standardních štětců
15. Barva pozadí oblasti nevyplněné štětcem
16. Sedmý demonstrační příklad: specifikace barvy pozadí a použití standardních štětců
17. Repositář s demonstračními příklady
1. Tvorba GUI v Pythonu s využitím frameworku PySide: grafické operace používající třídu QPainter
Na předchozí část seriálu o tvorbě grafického uživatelského rozhraní v Pythonu, v níž jsme si popsali základní vlastnosti tříd QImage, QPixmap a QBitmap, dnes navážeme. Ukážeme si totiž, jakým způsobem je možné vykreslovat základní geometrické (2D) tvary s využitím metod třídy QPainter. Tato třída totiž programátorům nabízí možnost vykreslení následujících tvarů a objektů:
Tvar/objekt | Metoda |
---|---|
bod | drawPoint() |
sada bodů | drawPoints() |
úsečka | drawLine() |
sada úseček | drawLines() |
obdélník | drawRect(), fillRect() |
sada obdélníků | drawRects() |
obdélník se zakulacenými rohy | drawRoundRect(), drawRoundedRect() |
polyčára (lomená úsečka) | drawPolyline() |
polygon | drawPolygon(), drawConvexPolygon() |
oblouk | drawArc() |
kruhová úseč | drawChord() |
kruhová výseč | drawPie() |
kružnice nebo elipsa | drawEllipse() |
obecná cesta | drawPath(), fillPath() |
text | drawText(), drawTextItem() |
rastrový obrázek | drawImage(), drawPicture(), drawPixmap(), … |
Podobně, jako je tomu například ve vektorovém formátu SVG, PostScriptu či v knihovně OpenVG, se i při použití QPainteru setkáme se třemi důležitými pojmy:
- Pero (pen) je nástroj použitý při vykreslování obrysu tvarů a samozřejmě i všech liniových tvarů (úsečky, oblouky, …).
- Štětec (brush) je nástroj použitý pro vyplnění uzavřených tvarů (obdélník, polygon, elipsa, cesta).
- Cesta (path) se používá k popisu složitějších tvarů složených z úseček a oblouků. Nad cestami je definováno větší množství operací, například test, zda bod leží uvnitř objektu popsaného cestou atd.
Dnes se seznámíme především s použitím per a štětců.
2. Základní operace podporované třídou QPainter: kreslení do rastrového obrázku
Samotný objekt QPainter provádí vykreslení na nějaké „plátno“, což může být buď přímo hardwarové zařízení (grafický subsystém), nebo rastrový obrázek. Podívejme se nyní na způsob vykreslení velmi jednoduché grafiky na rastrový obrázek s využitím možností nabízených třídou QPainter. Jeden z možných postupů je následující:
- Vytvoření instance třídy QImage, která bude tvořit „plátno“ pro QPainter. Konstruktoru QImage se předává rozlišení (počet sloupců a řádků) rastrového obrázku i formát pixelů. Nejjednodušší (i když ne vždy nejrychlejší) je použít formát QtGui.QImage.Format_RGB32 pro plnobarevné obrázky.
- Vytvoření objektu typu QPainter konstruktorem QPainter() (tento konstruktor nemá v nejjednodušším případě žádné parametry).
- Informace instance třídy QPainter o začátku vykreslování do instance třídy QImage. To se provede zavoláním metody QPainter.begin().
- Provedení vlastního vykreslení (například barevné úsečky). Mezi příkazovými závorkami begin a end můžete zavolat libovolné množství vykreslovacích operací.
- Informace QPainteru o ukončení vykreslování. To se provede zavoláním metody QPainter.end().
- Konverze objektu typu QImage na QPixmap (nebo QBitmap). Této problematice jsme se věnovali ve druhé kapitole předchozího článku.
- QPixmap či QBitmap lze již přímo vykreslit, například umístěním na návěští. I touto problematikou jsme se zabývali minule.
3. Praktický postup při vykreslování
V praxi se jednotlivé body výše uvedeného postupu budou implementovat následujícím způsobem:
Nejprve vytvoříme rastrový obrázek, který bude představovat „plátno“, na které bude třída QPainter vykreslovat obrazce:
image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32)
Dále vytvoříme objekt typu QPainter:
qp = QtGui.QPainter()
Informujeme tento objekt o začátku změn (vykreslování) do instance třídy QImage:
qp.begin(self.image)
Provedeme vlastní vykreslování – nastavíme barvu pera a vykreslíme tímto perem diagonální úsečku (povšimněte si, že se nemusíme nijak starat o to, kdy zanikne platnost objektu typu QColor – některé jiné toolkity totiž vyžadují explicitní uvolnění prostředků):
qp.setPen(QtGui.QColor(64, 255, 64)) qp.drawLine(10, 10, MainWindow.IMAGE_WIDTH-10, MainWindow.IMAGE_HEIGHT-10)
Informujeme objekt o konci změn (vykreslování):
qp.end()
V předposledním kroku se provede konverze objektu typu QImage na QPixmap:
pixmap = QtGui.QPixmap.fromImage(image)
Někde v další části kódu již můžeme pixmapu bez problémů vložit na navěští a tím ji vykreslit (resp. přesněji řečeno zobrazit uživateli):
label = QtGui.QLabel("test") label.setPixmap(pixmap) self.setCentralWidget(label)
Obrázek 1: Úsečka vykreslená příkazy popsanými v této kapitole.
4. První demonstrační příklad: použití metod QPainter.begin a QPainter.end
Výše uvedený postup pro vykreslení grafiky používající třídy QPainter a QImage je použit v dnešním prvním demonstračním příkladu, jehož úplný zdrojový kód vypadá následovně:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 256 IMAGE_HEIGHT = 256 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter qp = QtGui.QPainter() # začátek změn qp.begin(self.image) # nastavení barvy kreslení qp.setPen(QtGui.QColor(64, 255, 64)) # vykreslení úsečky qp.drawLine(10, 10, MainWindow.IMAGE_WIDTH-10, MainWindow.IMAGE_HEIGHT-10) # konec změn qp.end() # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
5. Použití „chytrého“ konstruktoru objektu typu QPainter
Třídu QPainter jsme prozatím používali takovým způsobem, že jsme nejprve vytvořili (zkonstruovali) instanci této třídy, následně jsme zavolali metodu QPainter.begin() s předáním obrázku, na který se bude kreslit, provedli jsme vlastní vykreslení a posléze jsme vykreslení explicitně ukončili metodou QPainter.end():
# vytvoření objektu typu QPainter qp = QtGui.QPainter() # začátek změn qp.begin(self.image) # nastavení barvy kreslení qp.setPen(QtGui.QColor(64, 255, 64)) # vykreslení úsečky qp.drawLine(10, 10, MainWindow.IMAGE_WIDTH-10, MainWindow.IMAGE_HEIGHT-10) # konec změn qp.end()
Tento postup měl nevýhodu v tom, že si programátor musí sám ohlídat použití metod QPainter.begin() a QPainter.end(). Tyto metody se vždy musí vyskytovat v páru a nesmí se překrývat, tj. nelze například dvakrát zavolat QPainter.begin() pro různé obrázky bez předchozího zavolání QPainter.end(). Navíc by se měla hlídat i návratová hodnota z první uvedené metody (True/False), což je test, který jsme pro jednoduchost vynechali. Tento poměrně nízkoúrovňový přístup můžeme obejít tak, že už při konstrukci objektu QPainter předáme konstruktoru rastrový obrázek, na který se má provést vlastní vykreslení:
# vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # nastavení barvy kreslení qp.setPen(QtGui.QColor(64, 255, 64)) # vykreslení úsečky qp.drawLine(10, 10, MainWindow.IMAGE_WIDTH-10, MainWindow.IMAGE_HEIGHT-10)
V tomto případě nemusíme explicitně volat metodu QPainter.begin(), protože tato operace se provede automaticky. Mnohem zajímavější je, že i metoda QPainter.end() se zavolá automaticky, a to konkrétně v destruktoru objektu typu QPainter (to mj. znamená, že by tento objekt měl mít pouze lokální viditelnost resp. oblast platnosti – pro jednoduchost by se celé vykreslení mělo provést v jediné metodě).
Obrázek 2: Výsledkem je naprosto stejné okno, jako v prvním příkladu.
6. Druhý demonstrační příklad: použití „chytrého“ konstruktoru objektu typu QPainter
Jakým způsobem je možné využít „chytrý“ konstruktor objektu typu QPainter je ukázáno v dnešním druhém demonstračním příkladu, jehož úplný zdrojový kód je vypsán pod tímto odstavcem:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 256 IMAGE_HEIGHT = 256 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # nastavení barvy kreslení qp.setPen(QtGui.QColor(64, 255, 64)) # vykreslení úsečky qp.drawLine(10, 10, MainWindow.IMAGE_WIDTH-10, MainWindow.IMAGE_HEIGHT-10) # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
7. Modifikace barvy a šířky pera použitého při vykreslování
Podívejme se nyní na modifikaci stylu vykreslovaných objektů. Již v úvodní kapitole jsme si řekli, že při kreslení obrysů uzavřených objektů i všech liniových objektů se používá nástroj nazvaný pero (pen) představovaný instancí třídy QPen. Při konstrukci objektu typu QPen můžeme specifikovat mj. i barvu kreslení. Následně se pero přiřadí instanci třídy QPainter. Změna barvy kreslení tedy může v tom nejjednodušším případě vypadat následovně:
pen = QtGui.QPen(barva) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen)
Barva je představována instancí třídy QColor a lze ji specifikovat v konstruktoru této třídy následujícími způsoby:
Parametry | Význam |
---|---|
rgb | jediná celočíselná hodnota (long) s kódem RGB |
red, green, blue | tři barvové složky: červená, zelená, modrá |
red, green, blue, alpha | tři barvové složky doplněné o průhlednost |
name | jméno barvy (viz následující kapitolu) |
PySide.QtCore.Qt.GlobalColor | jedna z dvaceti globálních barev |
Pozor: pokud se barva explicitně nespecifikuje, je pro kreslení použita černá barva, takže na implicitně černém obrázku nebude kresba viditelná!
Šířku kreslení (stopy) je možné zadat buď v konstruktoru třídy QPen (ovšem potom nelze specifikovat barvu), nebo zavoláním metody QPen.setWidth():
pen = QtGui.QPen(barva) # změna šířky pera pen.setWidth(width) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen)
Implicitně je šířka stopy nastavena na nulu; to odpovídá nejmenší možné stopě kreslení (jeden pixel bez použití antialiasingu).
8. Názvy barev s paletě knihovny PySide
Názvy všech barev uložených do standardní palety knihovny PySide získáme velmi snadno zavoláním statické metody QtGui.QColor.colorNames(), která vrátí seznam názvů známých barev. Tento seznam si samozřejmě můžeme velmi snadno vypsat, například následujícím jednořádkovým příkazem:
print("\n".join(QtGui.QColor.colorNames()))
Výstup by měl vypadat následovně (PySide 1.2.x):
aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato transparent turquoise violet wheat white whitesmoke yellow yellowgreen
Příklad použití jména barvy:
# vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen("gold") # kreslit se bude právě vytvořeným perem qPainter.setPen(pen)
9. Třetí demonstrační příklad: modifikace barvy a šířky pera
V dnešním třetím příkladu je ukázáno, jak je možné kreslit různobarevné úsečky s volitelnou šířkou stopy. O samotné kreslení úseček se stará uživatelská funkce drawLine():
# funkce pro vykreslení úsečky zadanou barvou def drawLine(qPainter, color, x1, y1, x2, y2, width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(width) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen) # vykreslení úsečky qPainter.drawLine(x1, y1, x2, y2)
Tato funkce v příkladu několikrát zavolána, takže vznikne následující kresba:
Obrázek 3: Okno vykreslené třetím příkladem.
Následuje výpis úplného zdrojového kódu tohoto příkladu:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys import math # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # funkce pro vykreslení úsečky zadanou barvou def drawLine(qPainter, color, x1, y1, x2, y2, width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(width) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen) # vykreslení úsečky qPainter.drawLine(x1, y1, x2, y2) # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 320 IMAGE_HEIGHT = 240 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # konstanty s n-ticemi představujícími základní barvy BLACK = (0, 0, 0) BLUE = (0, 0, 255) CYAN = (0, 255, 255) GREEN = (0, 255, 0) YELLOW = (255, 255, 0) RED = (255, 0, 0) MAGENTA = (255, 0, 255) WHITE = (255, 255, 255) # Vykreslení čar různou barvou drawLine(qp, BLUE, 10, 10, 160, 20) drawLine(qp, CYAN, 10, 20, 160, 30) drawLine(qp, GREEN, 10, 30, 160, 40) drawLine(qp, YELLOW, 10, 40, 160, 50) drawLine(qp, RED, 10, 50, 160, 60) drawLine(qp, MAGENTA, 10, 60, 160, 70) # Vykreslení čar s různým sklonem for i in range(1, 90, 5): # převod ze stupňů na radiány angle = math.radians(i) radius = 150 # výpočet koncových bodů úseček x = radius * math.sin(math.radians(i)) y = radius * math.cos(math.radians(i)) # vykreslení jedné úsečky drawLine(qp, WHITE, MainWindow.IMAGE_WIDTH-1, 0, MainWindow.IMAGE_WIDTH-x, y) # vykreslení čar různou šířkou for i in range(1, 10): drawLine(qp, WHITE, 10 + i*15, 90, 20 + i*15, 230, i) # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
10. Čtvrtý demonstrační příklad: použití antialiasingu při vykreslování
Při kreslení objektů do rastrového obrázku je možné kdykoli zapnout či naopak vypnout antialiasing (aa). To se provádí metodou QPainter.setRenderHint(), které se předá konstanta QPainter.Antialiasing, popř. kombinace konstant QPainter.Antialiasing, QPainter.TextAntialiasing a QPainter.HighQualityAntialiasing:
# vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) qp.setRenderHint(QtGui.QPainter.Antialiasing)
V případě, že potřebujeme antialiasing vypnout (kresba různých schémat atd.), předejte metodě QPainter.setRenderHint() pojmenovaný parametr on=False (implicitně má totiž hodnotu True):
# vypneme antialiasing qp.setRenderHint(QtGui.QPainter.Antialiasing, on=False)
Obrázek 4: Stejná scéna jako v předchozím příkladu, ovšem nyní vykreslená s využitím antialiasingu.
Pro porovnání rozdílů mezi nepoužitím a použitím antialiasingu si porovnejte následující dva obrázky:
Obrázek 5: Detail šikmých úseček vykreslených bez použití antialiasingu (zvětšeno).
Obrázek 6: Detail šikmých úseček vykreslených s použitím antialiasingu (zvětšeno).
Dnešní čtvrtý demonstrační příklad obsahuje ukázku zapnutí antialiasingu při kreslení úseček:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys import math # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # funkce pro vykreslení úsečky zadanou barvou def drawLine(qPainter, color, x1, y1, x2, y2, width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(width) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen) # vykreslení úsečky qPainter.drawLine(x1, y1, x2, y2) # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 320 IMAGE_HEIGHT = 240 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) qp.setRenderHint(QtGui.QPainter.Antialiasing) # konstanty s n-ticemi představujícími základní barvy BLACK = (0, 0, 0) BLUE = (0, 0, 255) CYAN = (0, 255, 255) GREEN = (0, 255, 0) YELLOW = (255, 255, 0) RED = (255, 0, 0) MAGENTA = (255, 0, 255) WHITE = (255, 255, 255) # Vykreslení čar různou barvou drawLine(qp, BLUE, 10, 10, 160, 20) drawLine(qp, CYAN, 10, 20, 160, 30) drawLine(qp, GREEN, 10, 30, 160, 40) drawLine(qp, YELLOW, 10, 40, 160, 50) drawLine(qp, RED, 10, 50, 160, 60) drawLine(qp, MAGENTA, 10, 60, 160, 70) # Vykreslení čar s různým sklonem for i in range(1, 90, 5): # převod ze stupňů na radiány angle = math.radians(i) radius = 150 # výpočet koncových bodů úseček x = radius * math.sin(math.radians(i)) y = radius * math.cos(math.radians(i)) # vykreslení jedné úsečky drawLine(qp, WHITE, MainWindow.IMAGE_WIDTH-1, 0, MainWindow.IMAGE_WIDTH-x, y) # vykreslení čar různou šířkou for i in range(1, 10): drawLine(qp, WHITE, 10 + i*15, 90, 20 + i*15, 230, i) # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
11. Čárkované a čerchované úsečky
Při kresbě liniových obrazců nebo okrajů plošných obrazců je možné zvolit vzorek (styl) úseček – plná (výchozí nastavení), čárkovaná, čerchovaná, střídavá apod. K nastavení vzorku vykreslení úsečky slouží metoda QPen.setDashPattern(). Parametrem této metody je seznam délek vykreslených segmentů prokládaných délkami segmentů nevykreslených. Podívejme se na jednoduchý příklad. Nejprve si vytvoříme pomocnou funkci pro vykreslení úsečky s volitelným vzorkem:
# funkce pro vykreslení úsečky zadanou barvou def drawDashedLine(qPainter, color, x1, y1, x2, y2, pattern): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna typu čáry pen.setStyle(QtCore.Qt.CustomDashLine) pen.setDashPattern(pattern) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen) # vykreslení úsečky qPainter.drawLine(x1, y1, x2, y2)
Tuto funkci použijeme pro vykreslení čar s různým vzorkem:
# Vykreslení čar různým stylem drawDashedLine(qp, YELLOW, 10, 10, 160, 10, [1, 1]) drawDashedLine(qp, YELLOW, 10, 20, 160, 20, [1, 10]) drawDashedLine(qp, YELLOW, 10, 30, 160, 30, [10, 1]) drawDashedLine(qp, YELLOW, 10, 40, 160, 40, [10, 10]) drawDashedLine(qp, YELLOW, 10, 50, 160, 50, [10, 1, 10, 5]) drawDashedLine(qp, YELLOW, 10, 60, 160, 60, [5, 5])
Podívejme se nyní na výsledek:
Obrázek 7: Různé vzorky čar (zvětšeno 2×).
Při kreslení šikmých úseček je situace složitější, protože délky nebudou přesně odpovídat (ty platí jen pro vodorovné či svislé tvary):
# Vykreslení čar s různým sklonem for i in range(1, 90, 5): # převod ze stupňů na radiány angle = math.radians(i) radius = 150 # výpočet koncových bodů úseček x = radius * math.sin(math.radians(i)) y = radius * math.cos(math.radians(i)) # vykreslení jedné úsečky drawDashedLine(qp, WHITE, MainWindow.IMAGE_WIDTH-1, 0, MainWindow.IMAGE_WIDTH-x, y, [5, 5])
Obrázek 8: Šikmé úsečky (zvětšeno 2×, používá se antialiasing).
Zajímavé bude také sledovat, co se stane při změně šířky pera, tj. šířky kreslené stopy. Výše uvedenou funkci si nepatrně upravíme tak, aby akceptovala další nepovinný parametr s šířkou:
# funkce pro vykreslení úsečky zadanou barvou def drawDashedLine(qPainter, color, x1, y1, x2, y2, pattern, width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(width) # změna typu čáry pen.setStyle(QtCore.Qt.CustomDashLine) pen.setDashPattern(pattern) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen) # vykreslení úsečky qPainter.drawLine(x1, y1, x2, y2)
Zkusíme si vykreslit několik úseček s různou tloušťkou:
# vykreslení čar různou šířkou for i in range(1, 10): drawDashedLine(qp, WHITE, 10 + i*15, 90, 10 + i*15, 230, [5, 5], i)
Výsledek je možná překvapivý:
Obrázek 9: Šířka pera ovlivňuje i délku vzorků (zvětšeno 2×).
12. Pátý demonstrační příklad: kresba čárkovaných a čerchovaných úseček
Postup při kreslení úseček s různým stylem je ukázán v dalším – dnes již pátém – demonstračním příkladu, po jehož spuštění by se měl vykreslit tento obrázek:
Obrázek 10: Okno vykreslené pátým demonstračním příkladem.
Následuje výpis zdrojového kódu tohoto příkladu:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys import math # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # funkce pro vykreslení úsečky zadanou barvou def drawDashedLine(qPainter, color, x1, y1, x2, y2, pattern, width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(width) # změna typu čáry pen.setStyle(QtCore.Qt.CustomDashLine) pen.setDashPattern(pattern) # kreslit se bude právě vytvořeným perem qPainter.setPen(pen) # vykreslení úsečky qPainter.drawLine(x1, y1, x2, y2) # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 320 IMAGE_HEIGHT = 240 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # konstanty s n-ticemi představujícími základní barvy BLACK = (0, 0, 0) BLUE = (0, 0, 255) CYAN = (0, 255, 255) GREEN = (0, 255, 0) YELLOW = (255, 255, 0) RED = (255, 0, 0) MAGENTA = (255, 0, 255) WHITE = (255, 255, 255) # Vykreslení čar různým stylem drawDashedLine(qp, YELLOW, 10, 10, 160, 10, [1, 1]) drawDashedLine(qp, YELLOW, 10, 20, 160, 20, [1, 10]) drawDashedLine(qp, YELLOW, 10, 30, 160, 30, [10, 1]) drawDashedLine(qp, YELLOW, 10, 40, 160, 40, [10, 10]) drawDashedLine(qp, YELLOW, 10, 50, 160, 50, [10, 1, 10, 5]) drawDashedLine(qp, YELLOW, 10, 60, 160, 60, [5, 5]) qp.setRenderHint(QtGui.QPainter.Antialiasing) # Vykreslení čar s různým sklonem for i in range(1, 90, 5): # převod ze stupňů na radiány angle = math.radians(i) radius = 150 # výpočet koncových bodů úseček x = radius * math.sin(math.radians(i)) y = radius * math.cos(math.radians(i)) # vykreslení jedné úsečky drawDashedLine(qp, WHITE, MainWindow.IMAGE_WIDTH-1, 0, MainWindow.IMAGE_WIDTH-x, y, [5, 5]) # vykreslení čar různou šířkou for i in range(1, 10): drawDashedLine(qp, WHITE, 10 + i*15, 90, 10 + i*15, 230, [5, 5], i) # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
13. Použití štětců při kreslení vyplněných grafických objektů
V úvodní kapitole jsme si řekli, že při kreslení uzavřených tvarů (obdélník, polygon, elipsa, cesta) je možné takové tvary vyplnit, přičemž pro vyplnění se používá nástroj nazvaný jednoduše štětec (brush. Štětec může být představován bitmapou (je to jedna z několika praktických možností použití bitmap ve frameworku PySide), popř. je možné štětec vybrat z připraveného vzorníku. Dnes se pro jednoduchost budeme zabývat právě existujícími vzorky štětců. Každý vzorek je představován jednou z konstant:
QtCore.Qt.SolidPattern QtCore.Qt.HorPattern QtCore.Qt.VerPattern QtCore.Qt.CrossPattern QtCore.Qt.BDiagPattern QtCore.Qt.FDiagPattern QtCore.Qt.DiagCrossPattern QtCore.Qt.Dense1Pattern QtCore.Qt.Dense2Pattern QtCore.Qt.Dense3Pattern QtCore.Qt.Dense4Pattern QtCore.Qt.Dense5Pattern QtCore.Qt.Dense6Pattern QtCore.Qt.Dense7Pattern
Obrázek 11: Vzorník výše vypsaných štětců (v daném pořadí).
Vzorky štětců se nastavují takto (podtržená část kódu):
# funkce pro vykreslení obdélníku zadanou barvou a se specifikovaným štětcem def drawRectangleUsingBrush(qPainter, color, x, y, width, height, brush_style, pen_width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(pen_width) qPainter.setPen(pen) # změna tvaru štětce brush = QtGui.QBrush(QtGui.QColor(*color)) brush.setStyle(brush_style) qPainter.setBrush(brush) # vykreslení obdélníku qPainter.drawRect(x, y, width, height)
Povšimněte si, že musíme specifikovat i barvu štětce, která se může lišit od barvy pera.
14. Šestý demonstrační příklad: vzorník standardních štětců
V šestém příkladu jsou ukázány základní vzorky štětců, které jsme si popsali v předchozí kapitole, takže se jen podívejme, jak může vypadat kód, který vzorník po svém spuštění vytiskne:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys import math # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # funkce pro vykreslení obdélníku zadanou barvou a se specifikovaným štětcem def drawRectangleUsingBrush(qPainter, color, x, y, width, height, brush_style, pen_width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(pen_width) qPainter.setPen(pen) # změna tvaru štětce brush = QtGui.QBrush(QtGui.QColor(*color)) brush.setStyle(brush_style) qPainter.setBrush(brush) # vykreslení obdélníku qPainter.drawRect(x, y, width, height) # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 440 IMAGE_HEIGHT = 140 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # konstanty s n-ticemi představujícími základní barvy BLACK = (0, 0, 0) BLUE = (0, 0, 255) CYAN = (0, 255, 255) GREEN = (0, 255, 0) YELLOW = (255, 255, 0) RED = (255, 0, 0) MAGENTA = (255, 0, 255) WHITE = (255, 255, 255) # Vykreslení obdélníků různým stylem drawRectangleUsingBrush(qp, YELLOW, 10, 10, 50, 50, QtCore.Qt.SolidPattern) drawRectangleUsingBrush(qp, YELLOW, 70, 10, 50, 50, QtCore.Qt.HorPattern) drawRectangleUsingBrush(qp, YELLOW, 130, 10, 50, 50, QtCore.Qt.VerPattern) drawRectangleUsingBrush(qp, YELLOW, 190, 10, 50, 50, QtCore.Qt.CrossPattern) drawRectangleUsingBrush(qp, YELLOW, 250, 10, 50, 50, QtCore.Qt.BDiagPattern) drawRectangleUsingBrush(qp, YELLOW, 310, 10, 50, 50, QtCore.Qt.FDiagPattern) drawRectangleUsingBrush(qp, YELLOW, 370, 10, 50, 50, QtCore.Qt.DiagCrossPattern) drawRectangleUsingBrush(qp, WHITE, 10, 70, 50, 50, QtCore.Qt.Dense1Pattern) drawRectangleUsingBrush(qp, WHITE, 70, 70, 50, 50, QtCore.Qt.Dense2Pattern) drawRectangleUsingBrush(qp, WHITE, 130, 70, 50, 50, QtCore.Qt.Dense3Pattern) drawRectangleUsingBrush(qp, WHITE, 190, 70, 50, 50, QtCore.Qt.Dense4Pattern) drawRectangleUsingBrush(qp, WHITE, 250, 70, 50, 50, QtCore.Qt.Dense5Pattern) drawRectangleUsingBrush(qp, WHITE, 310, 70, 50, 50, QtCore.Qt.Dense6Pattern) drawRectangleUsingBrush(qp, WHITE, 370, 70, 50, 50, QtCore.Qt.Dense7Pattern) # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
15. Barva pozadí oblasti nevyplněné štětcem
Při vyplňování uzavřených tvarů štětcem je možné si zvolit i barvu pozadí, přičemž pozadím jsou v tomto kontextu myšleny ty pixely, které sice leží uvnitř tvaru, ale štětec je při kreslení vynechá (nejedná se tedy o pozadí celé kreslicí plochy – plátna). Barva pozadí je stavová veličina a je ji možné kdykoli změnit (to ovlivní další vykreslování, nikoli však již vykreslené objekty). Navíc nezapomeňte, že kromě barvy pozadí je nutné nastavit i režim vykreslování pozadí na hodnotu QtCore.Qt.BGMode.OpaqueMode, protože implicitně se používá průhledné pozadí (přesněji řečeno nejsou pixely pozadí vůbec modifikovány). Podívejme se na příklad:
# vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # barva pozadi a povoleni vykreslení pozadi (vyplne) qp.setBackgroundMode(QtCore.Qt.BGMode.OpaqueMode) qp.setBackground(QtGui.QColor(red, green, blue))
16. Sedmý demonstrační příklad: specifikace barvy pozadí a použití standardních štětců
Sedmý a současně i dnešní poslední demonstrační příklad se od příkladu šestého odlišuje jen tím, že je v něm explicitně specifikována barva pozadí při použití standardních štětců. Vykreslený obrázek se tedy změní z:
Obrázek 12: Rozdíl mezi použitím a nepoužitím pozadí při vykreslování plochy tvarů štětci.
Samozřejmě opět následuje výpis zdrojového kódu tohoto příkladu:
#!/usr/bin/env python # vim: set fileencoding=utf-8 import sys import math # import "jádra" frameworku Qt i modulu pro GUI from PySide import QtCore from PySide import QtGui # funkce pro vykreslení obdélníku zadanou barvou a se specifikovaným štětcem def drawRectangleUsingBrush(qPainter, color, x, y, width, height, brush_style, pen_width=0): # vytvoření pera a nastavení barvy kreslení pen = QtGui.QPen(QtGui.QColor(*color)) # změna šířky pera pen.setWidth(pen_width) qPainter.setPen(pen) # změna tvaru štětce brush = QtGui.QBrush(QtGui.QColor(*color)) brush.setStyle(brush_style) qPainter.setBrush(brush) # vykreslení obdélníku qPainter.drawRect(x, y, width, height) # nový widget bude odvozen od obecného hlavního okna class MainWindow(QtGui.QMainWindow): # rozměry rastrového obrázku IMAGE_WIDTH = 440 IMAGE_HEIGHT = 140 def __init__(self): # zavoláme konstruktor předka super(MainWindow, self).__init__() self.prepareImage() # konfigurace GUI + přidání widgetu do okna self.prepareGUI() def prepareImage(self): # vytvoření instance třídy QImage self.image = QtGui.QImage(MainWindow.IMAGE_WIDTH, MainWindow.IMAGE_HEIGHT, QtGui.QImage.Format_RGB32) # vytvoření objektu typu QPainter s předáním # reference na "pokreslovaný" objekt qp = QtGui.QPainter(self.image) # konstanty s n-ticemi představujícími základní barvy BLACK = (0, 0, 0) BLUE = (0, 0, 255) CYAN = (0, 255, 255) GREEN = (0, 255, 0) YELLOW = (255, 255, 0) RED = (255, 0, 0) MAGENTA = (255, 0, 255) WHITE = (255, 255, 255) # barva pozadi a povoleni vykreslení pozadi (vyplne) qp.setBackgroundMode(QtCore.Qt.BGMode.OpaqueMode) qp.setBackground(QtGui.QColor(*BLUE)) # Vykreslení obdélníků různým stylem drawRectangleUsingBrush(qp, YELLOW, 10, 10, 50, 50, QtCore.Qt.SolidPattern) drawRectangleUsingBrush(qp, YELLOW, 70, 10, 50, 50, QtCore.Qt.HorPattern) drawRectangleUsingBrush(qp, YELLOW, 130, 10, 50, 50, QtCore.Qt.VerPattern) drawRectangleUsingBrush(qp, YELLOW, 190, 10, 50, 50, QtCore.Qt.CrossPattern) drawRectangleUsingBrush(qp, YELLOW, 250, 10, 50, 50, QtCore.Qt.BDiagPattern) drawRectangleUsingBrush(qp, YELLOW, 310, 10, 50, 50, QtCore.Qt.FDiagPattern) drawRectangleUsingBrush(qp, YELLOW, 370, 10, 50, 50, QtCore.Qt.DiagCrossPattern) drawRectangleUsingBrush(qp, WHITE, 10, 70, 50, 50, QtCore.Qt.Dense1Pattern) drawRectangleUsingBrush(qp, WHITE, 70, 70, 50, 50, QtCore.Qt.Dense2Pattern) drawRectangleUsingBrush(qp, WHITE, 130, 70, 50, 50, QtCore.Qt.Dense3Pattern) drawRectangleUsingBrush(qp, WHITE, 190, 70, 50, 50, QtCore.Qt.Dense4Pattern) drawRectangleUsingBrush(qp, WHITE, 250, 70, 50, 50, QtCore.Qt.Dense5Pattern) drawRectangleUsingBrush(qp, WHITE, 310, 70, 50, 50, QtCore.Qt.Dense6Pattern) drawRectangleUsingBrush(qp, WHITE, 370, 70, 50, 50, QtCore.Qt.Dense7Pattern) # vytvoření instance třídy QPixmap z objektu QImage self.pixmap = QtGui.QPixmap.fromImage(self.image) def prepareGUI(self): # velikost okna nezadávejte ručně - špatně se počítá kvůli toolbaru # self.resize(256, 300) self.setWindowTitle('QPainter') # tlačítko Quit quitAction = QtGui.QAction(QtGui.QIcon('icons/application-exit.png'), '&Quit', self) quitAction.triggered.connect(self.close) quitAction.setStatusTip('Quit the application') quitAction.setShortcut('Ctrl+Q') # nástrojový pruh self.toolbar = self.addToolBar('title') self.toolbar.setMovable(False) # přidání tlačítka na nástrojový pruh self.toolbar.addAction(quitAction) # doprostřed okna přidáme návěští s rastrovým obrázkem self.addLabelWithPixmap() # zobrazení hlavního okna self.show() def addLabelWithPixmap(self): # vytvoření návěští label = QtGui.QLabel("test") # přiřazení rastrového obrázku k návěští label.setPixmap(self.pixmap) # vložení návěští do hlavního okna self.setCentralWidget(label) def run(self, app): # zobrazení okna na obrazovce self.show() # vstup do smyčky událostí (event loop) app.exec_() def main(): app = QtGui.QApplication(sys.argv) MainWindow().run(app) if __name__ == '__main__': main()
17. Repositář s demonstračními příklady
Zdrojové kódy všech sedmi dnes popsaných demonstračních příkladů byly opět, podobně jako tomu bylo i v předchozích článcích, uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/presentations. Pokud nechcete klonovat celý repositář, můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:
Příklad | Adresa |
---|---|
63_qpainter.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/63_qpainter.py |
64_qpainter_smart_constructor.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/64_qpainter_smart_constructor.py |
65_pen_color_and_width.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/65_pen_color_and_width.py |
66_qpainter_aa.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/66_qpainter_aa.py |
67_dashed_line.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/67_dashed_line.py |
68_brush_patterns.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/68_brush_patterns.py |
69_pattern_background.py | https://github.com/tisnik/presentations/blob/master/Python_GUI/PySide/69_pattern_background.py |
18. Odkazy na Internetu
- PySide 1.2.1 documentation
https://pyside.github.io/docs/pyside/index.html - QImage
https://pyside.github.io/docs/pyside/PySide/QtGui/QImage.html - QPixmap
https://pyside.github.io/docs/pyside/PySide/QtGui/QPixmap.html - QBitmap
https://pyside.github.io/docs/pyside/PySide/QtGui/QBitmap.html - QPaintDevice
https://pyside.github.io/docs/pyside/PySide/QtGui/QPaintDevice.html - QPicture
https://pyside.github.io/docs/pyside/PySide/QtGui/QPicture.html - QPainter
https://pyside.github.io/docs/pyside/PySide/QtGui/QPainter.html - QPainterPath
https://pyside.github.io/docs/pyside/PySide/QtGui/QPainterPath.html - Afinní zobrazení
https://cs.wikipedia.org/wiki/Afinn%C3%AD_zobrazen%C3%AD - Differences Between PySide and PyQt
https://wiki.qt.io/Differences_Between_PySide_and_PyQt - PySide 1.2.1 tutorials
https://pyside.github.io/docs/pyside/tutorials/index.html - PySide tutorial
http://zetcode.com/gui/pysidetutorial/ - Drawing in PySide
http://zetcode.com/gui/pysidetutorial/drawing/ - Qt Core
https://pyside.github.io/docs/pyside/PySide/QtCore/Qt.html - QLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QLayout.html - QStackedLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QStackedLayout.html - QFormLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QFormLayout.html - QBoxLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QBoxLayout.html - QHBoxLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QHBoxLayout.html - QVBoxLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QVBoxLayout.html - QGridLayout
https://pyside.github.io/docs/pyside/PySide/QtGui/QGridLayout.html - QAction
https://pyside.github.io/docs/pyside/PySide/QtGui/QAction.html - QMessageBox
https://pyside.github.io/docs/pyside/PySide/QtGui/QMessageBox.html - QListWidget
https://pyside.github.io/docs/pyside/PySide/QtGui/QListWidget.html - Signals & Slots
http://doc.qt.io/qt-4.8/signalsandslots.html - Signals and Slots in PySide
http://wiki.qt.io/Signals_and_Slots_in_PySide - Intro to PySide/PyQt: Basic Widgets and Hello, World!
http://www.pythoncentral.io/intro-to-pysidepyqt-basic-widgets-and-hello-world/ - QWidget
https://pyside.github.io/docs/pyside/PySide/QtGui/QWidget.html - QMainWindow
https://pyside.github.io/docs/pyside/PySide/QtGui/QMainWindow.html - QLabel
https://pyside.github.io/docs/pyside/PySide/QtGui/QLabel.html - QAbstractButton
https://pyside.github.io/docs/pyside/PySide/QtGui/QAbstractButton.html - QCheckBox
https://pyside.github.io/docs/pyside/PySide/QtGui/QCheckBox.html - QRadioButton
https://pyside.github.io/docs/pyside/PySide/QtGui/QRadioButton.html - QButtonGroup
https://pyside.github.io/docs/pyside/PySide/QtGui/QButtonGroup.html - QFrame
https://pyside.github.io/docs/pyside/PySide/QtGui/QFrame.html#PySide.QtGui.PySide.QtGui.QFrame - QFrame.frameStyle
https://pyside.github.io/docs/pyside/PySide/QtGui/QFrame.html#PySide.QtGui.PySide.QtGui.QFrame.frameStyle - Leo editor
http://leoeditor.com/ - IPython Qt Console aneb vylepšený pseudoterminál
https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-ipython-a-ipython-notebook/#k06 - Vývojová prostředí ve Fedoře (4. díl)
https://mojefedora.cz/vyvojova-prostredi-ve-fedore-4-dil/ - Seriál Letní škola programovacího jazyka Logo
http://www.root.cz/serialy/letni-skola-programovaciho-jazyka-logo/ - Educational programming language
http://en.wikipedia.org/wiki/Educational_programming_language - Logo Tree Project:
http://www.elica.net/download/papers/LogoTreeProject.pdf - Hra Breakout napísaná v Tkinteri
https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/ - Hra Snake naprogramovaná v Pythone s pomocou Tkinter
https://www.root.cz/clanky/hra-snake-naprogramovana-v-pythone-s-pomocou-tkinter/ - 24.1. turtle — Turtle graphics
https://docs.python.org/3.5/library/turtle.html#module-turtle - TkDND
http://freecode.com/projects/tkdnd - Python Tkinter Fonts
https://www.tutorialspoint.com/python/tk_fonts.htm - The Tkinter Canvas Widget
http://effbot.org/tkinterbook/canvas.htm - Ovládací prvek (Wikipedia)
https://cs.wikipedia.org/wiki/Ovl%C3%A1dac%C3%AD_prvek_%28po%C4%8D%C3%ADta%C4%8D%29 - Rezervovaná klíčová slova v Pythonu
https://docs.python.org/3/reference/lexical_analysis.html#keywords - TkDocs: Styles and Themes
http://www.tkdocs.com/tutorial/styles.html - Drawing in Tkinter
http://zetcode.com/gui/tkinter/drawing/ - Changing ttk widget text color (StackOverflow)
https://stackoverflow.com/questions/16240477/changing-ttk-widget-text-color - The Hitchhiker's Guide to Pyhton: GUI Applications
http://docs.python-guide.org/en/latest/scenarios/gui/ - 7 Top Python GUI Frameworks for 2017
http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/ - GUI Programming in Python
https://wiki.python.org/moin/GuiProgramming - Cameron Laird's personal notes on Python GUIs
http://phaseit.net/claird/comp.lang.python/python_GUI.html - Python GUI development
http://pythoncentral.io/introduction-python-gui-development/ - Graphic User Interface FAQ
https://docs.python.org/2/faq/gui.html#graphic-user-interface-faq - TkInter
https://wiki.python.org/moin/TkInter - Tkinter 8.5 reference: a GUI for Python
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html - TkInter (Wikipedia)
https://en.wikipedia.org/wiki/Tkinter - appJar
http://appjar.info/ - appJar (Wikipedia)
https://en.wikipedia.org/wiki/AppJar - appJar na Pythonhosted
http://pythonhosted.org/appJar/ - appJar widgets
http://appjar.info/pythonWidgets/ - Stránky projektu PyGTK
http://www.pygtk.org/ - PyGTK (Wikipedia)
https://cs.wikipedia.org/wiki/PyGTK - Stránky projektu PyGObject
https://wiki.gnome.org/Projects/PyGObject - Stránky projektu Kivy
https://kivy.org/#home - Stránky projektu PyQt
https://riverbankcomputing.com/software/pyqt/intro - PyQt (Wikipedia)
https://cs.wikipedia.org/wiki/PyGTK - Stránky projektu PySide
https://wiki.qt.io/PySide - PySide (Wikipedia)
https://en.wikipedia.org/wiki/PySide - Stránky projektu Kivy
https://kivy.org/#home - Kivy (framework, Wikipedia)
https://en.wikipedia.org/wiki/Kivy_(framework) - QML Applications
http://doc.qt.io/qt-5/qmlapplications.html - KDE
https://www.kde.org/ - Qt
https://www.qt.io/ - GNOME
https://en.wikipedia.org/wiki/GNOME - Category:Software that uses PyGTK
https://en.wikipedia.org/wiki/Category:Software_that_uses_PyGTK - Category:Software that uses PyGObject
https://en.wikipedia.org/wiki/Category:Software_that_uses_PyGObject - Category:Software that uses wxWidgets
https://en.wikipedia.org/wiki/Category:Software_that_uses_wxWidgets - GIO
https://developer.gnome.org/gio/stable/ - GStreamer
https://gstreamer.freedesktop.org/ - GStreamer (Wikipedia)
https://en.wikipedia.org/wiki/GStreamer - Wax Gui Toolkit
https://wiki.python.org/moin/Wax - Python Imaging Library (PIL)
http://infohost.nmt.edu/tcc/help/pubs/pil/ - Why Pyjamas Isn’t a Good Framework for Web Apps (blogpost z roku 2012)
http://blog.pyjeon.com/2012/07/29/why-pyjamas-isnt-a-good-framework-for-web-apps/