Qt framework v dnešní době představuje komplexní aplikační vývojový framework, který za relativně dlouhou dobu svého vývoje (téměř 21 let) vyrostl do podoby univerzálního nástroje umožňujícího tvorbu sofistikovaných multiplatformních aplikací. Ve své původní podobě to byl pouze tzv. widget toolkit neboli knihovna pro tvorbu grafických uživatelských rozhraní (GUI). Postupně však během vývoje přibývaly funkce a moduly pro podporu multimédií, databází, sítí, webových technologií a mnoho dalších komponent.

Z Qt frameworku se tak stala ucelená vývojářská platforma na jejímž základě lze postavit téměř libovolnou aplikaci, která bude nativně multiplatformní. Navíc při vývoji většinou není potřeba využívat téměř žádné externí knihovny, protože velká většina potřebné bázové funkcionality je už integrována do samotného Qt frameworku. Velkou výhodou je pak to, že pro aplikaci vystačíte pouze s jedinou sadou zdrojových kódu, které stačí pro nasazení na libovolnou další podporovanou platformu pouze jednoduše překompilovat.

Tento článek se však nezabývá celým Qt, které pouze stručně představuje, ale zaměřuje se pouze na možnosti grafiky a multimédií v tomto frameworku.

Historie Qt frameworku Vývoj Qt frameworku započal přibližně v roce 1991, kdy jej jeho dva hlavní vývojáři (Haavard Nord a Eirik Chambe-Eng) začali samostatně vyvíjet. První veřejně dostupná verze se pak objevila až v květnu 1995. Původní myšlenky na vytvoření multiplatformního toolkitu pro tvorbu GUI však pocházejí už z roku 1988 a 1990 tedy z dob studií obou jeho hlavních autorů na Norwegian Institute of Technology v Trondheimu.

Poznámka: Zajímavostí ohledně počátku vývoje Qt frameworku je, že tento vývoj sponzorovaly manželky dvou hlavních vývojářů, protože oba zmínění pánové v té době ještě neměli žádné jiné příjmy, kterými by se v té době zajistili. Vskutku se tedy jednalo o originální a unikátní vývojový model.

Původní vývoj tedy zastřešovali pouze dva vývojáři, kteří po relativním úspěchu svého produktu založili společnost Quasar Technologies později Trolltech. Trolltech zajišťoval vývoj Qt od roku 1995 do roku 2008. Poté technologii Qt odkoupila společnost Nokia, která se o jeho vývoj starala až do podzimu 2012. V současné době vývoj spravuje společnost Digia, která Qt zakoupila od Nokie. Digia však není ve vývoji Qt tak úplně nováčkem, protože k němu už předtím několik let poskytovala komerční podporu, vývoj a školení. V poslední době se dokonce starala o prodej komerčních licencí než celou technologii převzala kompletně.

Podporované platformy V současné době jsou podporovány tři majoritní desktopové platformy v podobě Microsoft Windows, Apple Mac OS X a UNIX/Linux-like systémy. Kromě nich však Qt podporuje i embedded platformy a mobilní zařízení (Symbian, embedded Linux…). V blízké budoucnosti (příchod finální verze Qt 5) se chystá také oficiální podpora Android OS, Apple iOS, BlackBerry a QNX.

Podporované programovací jazyky Nativním jazykem tohoto frameworku je jazyk C++, který je ovšem rozšířen o možnosti jako je introspekce, podpora mechanismu Signálu & Slotu a několik dalších vylepšení, které usnadňují a urychlují vývoj především aplikací s grafickým uživatelským rozhraním. Dalším nativně podporovaným jazykem je jazyk QML (Qt Markup/Modeling Language) což je v podstatě obdoba webového CSS pomocí kterého ve spolupráci s JavaScriptem lze jednoduše naskriptovat GUI aplikace a jádro poté pro větší efektivitu výsledného kódu napsat v jazyce C++. Kromě těchto dvou nativních možností ještě pro Qt existuje mnoho jazykových vazeb (anglicky language bindings), kde mezi nejvýznamnější patří například podpora pro Python, Ruby, Javu.

Licence a možnosti vývoje Qt framework je nabízen ve třech možných licenčních modelech. Nejprve je zde klasická licence, kdy si zakoupíte komerční licenci a můžete vyvíjet své aplikace i modifikovat samotný Qt framework bez jakékoli povinnosti zveřejňovat své kódy či platit nějaké licenční poplatky z prodaných aplikací. Poté je zde možnost možnost využít licence GPL (General Public Licence), kdy je možné zdarma nekomerčně vyvíjet, ale je nutné zveřejnit všechny zdrojové kódy vytvořené aplikace. Třetím typem licence je LGPL (Lesser GPL), která umožňuje uzavřený komerční vývoj aplikací, kdy vývojář je povinen zveřejnit pouze změny, které provedl v kódu samotného Qt frameworku.

Moduly Qt frameworku Celý framework je postaven na objektových konceptech a je velmi modulární, to v praxi znamená, že svůj projekt zkompilujete pouze s moduly, které využijete a nemusíte s aplikací přibalovat neužitečný kód. V základu se Qt framework skládá z následujících modulů: QtCore – jádro Qt a jeho základní nevizuální komponenty QtGui – bázový modul všech vizuálních prvků GUI tzv. widgetů QtMultimedia – nízkoúrovňová podpora pro multimédia QtNetwork – síťová podpora QtOpenGL – spolupráce s knihovnou OpenGL QtScript – možnost aplikačního skriptování QtSql – podpora práce s databázemi QtSvg – podpora vektorového grafického formátu SVG QtWebKit – jádro webového prohlížeče WebKit (práce s webem) QtXml – podpora technologie XML QtDeclarative – jádro a rozhraní pro spolupráci nativního kódu s deklarativním QML Phonon – komplexní multimediální framework a několik dalších..

Rastrové 2D kreslení pomocí systému Arthur Rastrové kreslení v Qt je v principu obdobné kreslení pomocí standardních Win32 API funkcí respektive grafickému modulu GDI (Graphics Device Interface), kde se pracuje s nejrůznějšími pery, výplňovými štětci a doplňkovými nástroji které modifikují určitý rastr. V systému Arthur je tento přístup zapouzdřen pomocí třech typů tříd. Vystupuje zde třída QPainter (malíř/kreslíř) která umožňuje vlastní kreslení na základě sekvenčních pokynů programátora. Poté je zde přítomno kreslící jádro QPaintEngine které přímo implementuje kreslící metody a abstrahuje QPainter od specifického kreslícího zařízení. Nakonec třída QPaintDevice zapouzdřuje samotné kreslící zařízení na které se bude vykreslovat.

Uživatel typicky přijde do styku pouze se třídami QPainter a QPaintDevice. Na určité kreslící zařízení je totiž třeba inicializovat QPainter a pak už pomocí něj pouze kreslit. Kreslí se v principu jako byste kreslili perem nebo obdobným nástrojem na papír či jiné médium. Tedy řekněme, že nakreslíte čtverec, poté trojúhelník atd. a ve výsledku z toho vznikne například dům. Abyste si vytvořili praktickou představu, podívejte se na ukázku níže. Díky obecnému principu lze takto kreslit na nejrůznější kreslící zařízení zahrnující vlastní widgety (QWidget), rastrové obrázky (QPixmap) a dokonce i tisknout (jako kreslící zařízení se využije třída QPrinter). Tímto systémem pak lze většinou kreslit pouze v kreslící události paintEvent() jednotlivých prvků, výjimkou je zde ale například tisk nebo renderování do rastru které lze provádět téměř v libovolné funkci či metodě.

void VlastniWidget::paintEvent(QPaintEvent *udalost) { QPainter painter(this); // instance QPainteru pro kreslení na vlastní widget painter.setRenderHint(QPainter::Antialiasing); // s vyhlazováním painter.setFont(QFont("Arial", 13, QFont::Normal, true)); // typ a styl písma

// vykreslení textu painter.drawText(10, 10, QString::fromUtf8("Můj dům:"));

// nastaveni stylu pera painter.setPen(QPen(QBrush(Qt::darkGreen), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter.drawRect(QRect(1, 10, 5, 4)); // vykreslení obdélníku

painter.setPen(Qt::black); painter.setPen(Qt::DotLine); for (int i = 0; (i < pocet_pi - 1); i++) { painter.drawLine(pi[i], pi[i + 1]); } }

// vykreslení čáry painter.drawLine(px, py); // atd..

udalost->accept(); }

Mezi kreslícími instrukcemi je k dispozici velké množství metod od těch elementárních pro kreslení čar (drawLine()), obdélníku (drawRect()) nebo elips (drawEllipse()) až po metody pro kreslení komplexnějších tvarů (drawPath()). Jako parametry jednotlivých entit lze kompletně nastavit jejich obrys (setPen()) a vyplň (setBrush()). Protože vykreslování pracuje stavově, jsou dané atributy aplikovány na další entity dokud nejsou jejich hodnoty přepsány jiným nastavením tedy voláním metody typu set*().

Při rastrovém kreslení se také hodí uchovávat si různé datové struktury typu bod (QPoint/F), čára (QLine/F), obdélník (QRect/F) či QPainterPath (obecná cesta) a QPainterPathStroker (parametry obecné cesty) apod. pro které Qt nabízí své vestavěné datové struktury. Postfix /F pak znamená, že například třída QRect představující parametry obdélníka existuje i ve variantě QRectF, která takovéto parametry uchovává v desetinné reprezentaci.

Vektorové 2D kreslení pomocí modulu Graphics View Framework Qt nabízí kromě rastrového kreslícího mechanismu také pokročilejší modelování 2D scény na základě vzoru model/pohled. V tomto případě nepracujete s kreslícími nástroji a rastrem ale s modelem scény, jejími entitami a pohledem či pohledy na takovouto scénu. Díky tomu, že dané entity scény vystupují samostatně a relativně nezávisle, je zde možnost selekce a interakce s prvky takovéto scény díky zabudovanému výběrovému a notifikačnímu mechanismu (ten je založen na implementaci BSP stromu). Princip práce s Graphics View Frameworkem je obecně takový, že si nejprve vytvoříte grafickou scénu (QGraphicsScene), která bude představovat model. Do této scény přidáte požadované entity (QGraphicsItem) jako jsou čáry (QGraphicsLineItem), obdélníky (QGraphicsRectItem), obrázky (QGraphicsPixmapItem a QGraphicsSvgItem) nebo vlastní komplexnější entity odvozené například ze třídy QGraphicsItem. A nakonec pouze vytvoříte pohled (QGraphicsView) který bude sloužit k vizualizaci daného výseku scény. Pohled je tedy obyčejný widget představující jakési plátno, které zobrazuje specifický výřez modelu scény. Pohledů může být samozřejmě i více a můžete takto sledovat současně více lokací ve scéně.

Z výše uvedeného je vidět, že se se scénou pracuje v principu vektorově, kdy máme k dispozici matematický popis scény (seznam entit s parametry) a nové entity zadáváme pouze parametricky, tedy neřešíme jak je vykreslit. Pokud se změní měřítko scény, entity se automatický přeškálují a jsou opět vykresleny v maximální možné kvalitě. Zde zmiňme dvě výjimky. Neomezeně a bezchybně nelze škálovat pouze obrázky typu QGraphicsPixmapItem, což plyne z jejich diskrétní povahy. A pak u vlastních entit je třeba napsat jejich vykreslovací metodu (realizovanou přes QPainter) tak, aby brala v potaz možnou změnu rozměrů dané entity vyvolanou změnou měřítka scény respektive jejího pohledu. Při vlastní práci s entitami a scénou je třeba myslet na vztahy různých souřadnicových systému a ty dle potřeby přemapovat. V základu je obecné schéma těchto vztahů následující: entita → rodičovská entita → scéna → pohled a zpět. K přemapování slouží metody s prefixem mapFrom/To*(). Vzhledem k obecné reprezentaci entit scény jsou pak umožněny efekty jako animace jednotlivých entit a jejich pokročilejší transformace, aplikace grafických efektů (rozmazání, vržený stín…) apod. Díky zabudované podpoře mechanismu Signálu & Slotu lze takto komunikovat mezi jednotlivými entitami ale i mezi klasickými widgety a prvky scény, což velmi zjednodušuje například psaní grafických aplikací, kdy nemusíme provádět vlastní přepočty z kurzoru na entity a složitě využívat různých callbacků (ukazatelů na funkce) pro komunikaci apod.

// vytvoření scény scena = new QGraphicsScene; // vytvoření modelu scény scena->setSceneRect(QRectF(0, 0, 200, 200)); // nastavení velikosti scena->setBackgroundBrush(QBrush(Qt::white)); // barva pozadí

// instalace pohledu pohled = new QGraphicsView(scena); // vytvoření pohledu pohled->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); pohled->setDragMode(QGraphicsView::RubberBandDrag); // povolení výběru oramováním

// přidání entit scena.addItem(new GraphicsLineItem(10, 10)); // stejně pro další entity..

OpenGL v Qt (3D grafika v Qt I.)