Jazyk C# (seminář 9) Pavel Procházka KMI 19. listopadu 2014
Motivace proč GTK# Moderní přístup k psaní GUI Základ (GTK+) je napsaný v C, ale podporuje celou řadu jazyků (Vala, Python, JavaScript, C#,... ) Umí relativně pozicovat objekty, zvětšovat zmenšovat, umí průhledně nakládat s DPI GUI widgety lze reprezentovat XML souborem Nativně ho podporuje MonoDevelop K editaci widgetů, oken slouží externí nástroj Glade nebo vestavěný nástroj do MonoDevelopu preferovaná varianta http://www.mono-project.com/docs/gui/gtksharp/ Negativum spočívá v tom, že GTK# je automatizovaně generované API místy ne zcela dokonale využívá možnosti C# Negativum je to, že lze méně naklikat než ve VisualStudiu
Designer pro GTK#
Principy GTK# GUI prvkům se říká widgety Nic se pevně nepozicuje Každý widget by měl být v nějakém kontejneru, který se automaticky zvětšuje a zmenšuje podle potřeby (podle velikosti vnořených widgetů) Rozeznáváme horizontální a vertikální kontejnery (a další speciální) Kontejnery jsou podobné div z HTML Na některé prvky můžeme mít specifické nároky na pevnou nebo minimální velikost, to lze (pomocí designeru záložka vlastnosti) Vykreslování uživatelské grafiky lze pomocí knihovny Cairo (nutné dodat referenci) Přímé vykreslování je možné pomocí Gdk
Hello world using System; using Gtk; class MainClass { public static void Main (string[] args) { Application.Init (); Window win = new Gtk.Window (0); win.title = "Hello World"; win.show (); Application.Run (); } }
Základní GUI widgety Třídy pro okna dialogy Gtk.Window, MessageDialog,... Kontejnery HBox, VBox,... Položkové seznamy NodeView, TreeView Základní widgety Button, ComboBox, RadioButton, ProgressBar Vykreslovací plátno DrawingArea Menu Menu, MenuBar, MenuItem Celá hierarchie widgetů je pěkně shrnutá tady https:// developer.gnome.org/gtk-tutorial/2.90/x477.html Práce se seznamy typu NodeView je pěkně shrnutá zde http://www.mono-project.com/docs/gui/gtksharp/ widgets/nodeview-tutorial-examples/
Kreslení vektorové grafiky pomocí Cairo Cairo je pokročilá knihovna pro kreslení vektorové grafiky, je akcelerovaná (tudíž rychlá) Podporuje antialiasing (výchozí) (pro objekty i pro text) Výstup je kvalitní a přesný (na rozdíl od GDI+) V budoucnosti bude Cairo pravděpodobně oficiální součástí C++ jako jeho standarní knihovna Knihovna s vnitřním stavem podobný koncept jako OpenGL Lze si to představit jako pastelku v ruce Vybíráme si barvu, jestli chceme obtahovat nebo vyplňovat atd. Potřeba doplnit referenci na Mono.Cairo a vložit namespace using Cairo; Opět knihovna obsahuje celou řadu metod Popisovač získáme Cairo pomocí Gdk.CairoHelper.Create, argumentem přebírá GdkWindow analogie k CreateGraphics(); GdkWindow je součástí každého uživatelsky kreslitelného objektu
Jak se to nakreslí?
Cairo jednoduchý příklad GTK# using (Cairo.Context cr = Gdk.CairoHelper.Create(area.GdkWindow)) { cr.linewidth = 9; cr.setsourcergb (0.7, 0.2, 0.0); int mw = (width <= height? width : height); cr.translate (width / 2, height / 2); cr.arc (0, 0, mw / 3,0, 2 * Math.PI); cr.strokepreserve (); cr.setsourcergb (0.3, 0.4, 0.6); cr.fill (); cr.setsourcergb (0.9, 0.9, 0.01); cr.arc (-(width / 9), -(width / 9), mw/14, 0, 2 * Math.PI ); cr.strokepreserve ();...
Cairo jednoduchý příklad cntd. cr.setsourcergb (0.9, 0.1, 0); cr.fill (); cr.setsourcergb (0.9, 0.9, 0.01); cr.arc ((width / 9), -(width / 9), mw/14, 0, 2 * Math.PI ); cr.strokepreserve (); cr.setsourcergb (0.9, 0.1, 0); cr.fill (); cr.setsourcergb (0.9, 0.9, 0.01); cr.arc (0, 0, mw/4, 0, 1 * Math.PI ); cr.strokepreserve (); cr.moveto (new PointD (0, mw / 12)); cr.lineto (new PointD (0, -(mw / 12))); cr.strokepreserve (); }
Kreslení per pixel Obrázek se reprezentuje pomocí třídy Gdk.Image Čtení pixelu se dělá pomocí GetPixel Zápis pixelu pomocí PutPixel POZOR: Tyto metody pracují s pixely ve formátu ARGB, které jsou uloženy v uint na každý kanál 1 bajt Je tedy nutné znát binární operace jako <<, &, apod. (ty ale už znáte z C) Lze si ulehčit práci skrze třídu Gdk.Color, která toto dělá za nás Kreslí se pomocí třídy GdkWindows a její metody DrawImage
Gdk přímy přístup k pixelům Gdk.Image im = area.gdkwindow.getimage (0, 0, width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { im.putpixel (x, y, im.getpixel(x,y) & 0x00ff0000 ); } } Console.WriteLine (im.getpixel (25, 25)); area.gdkwindow.drawimage ( /* ziskani kontextu -- kam kreslit */ Style.ForegroundGC (StateType.Normal), im, 0, 0, 0, 0, width, height);
A ted vy Vytvořte nástroj pro želví grafiku, který se dá zvětšovat a zmenšovat a zaznamenává tahy. Otočení želvy je po 45 stupních