programozás iii
DESCRIPTION
Programozás III. Ismétlés (Grafikai lehetőségek WPF-ben) Visual utódok. Grafikai lehetőségek WPF-ben. Shape-ek ( System.Windows.Shapes.Shape leszármazottak) Egyszerű, előre elkészített grafikai alakzatok Toolboxban is szerepelnek FrameworkElement utódok: input, fókusz, események… - PowerPoint PPT PresentationTRANSCRIPT
V 1.0
Programozás III.
Ismétlés (Grafikai lehetőségek WPF-ben)Visual utódok
V 1.0 ÓE-NIK, 2014
Grafikai lehetőségek WPF-ben• Shape-ek (System.Windows.Shapes.Shape
leszármazottak)– Egyszerű, előre elkészített grafikai alakzatok– Toolboxban is szerepelnek– FrameworkElement utódok: input, fókusz, események…– Csak kevés számú (max 100) objektum esetén
• Drawing objektumok (System.Windows.Media.Drawing leszármazottak)– Nincs belső támogatásuk input eseményekhez– Nem képesek maguktól a megjelenésre, hosztoló objektumban
kell őket elhelyezni– Legtöbbször XAML-ból kezeljük– Gyorsabb a Shape-eknél (max néhány 100 objektumig)
• Visual objektumok (System.Windows.Media.Visual)– Legbonyolultabb, leggyorsabb (max kb. 10000 objektumig)– XAML lehetőségek korlátozottak, mindig kódból kezeljük 2
V 1.0 ÓE-NIK, 2014
Visual
• Ahhoz biztosít szolgáltatásokat, hogy a leszármazott típus renderelhető legyen
• Több speciális célú utódosztály: pl. DrawingVisual (2D), Viewport3DVisual (3D)
• Az ezzel való rajzolásnak elsősorban kétféle variációja létezik:– Egy adott grafikusfelület-elem „vizuális gyermekei” (kirajzolandó
objektumok) közé beteszünk újabb Visual objektumokat– Egyedi leszármazott típust definiálunk valamelyik grafikusfelület-
elemből (tipikusan: FrameworkElement), kihasználva, hogy a GUI-elemek maguk is Visual utódok
3
V 1.0 ÓE-NIK, 2014
DrawingVisual• 2D rajzolásra
– RenderOpen() függvényét kell hívni, DrawingContext objektumot ad vissza
• A DrawingContext segítségével „tölthetjük fel” a Visualt (vagy egy DrawingGroupot) tartalommal– Pl. a következő függvények értelmezettek rajta:– DrawEllipse()– DrawRectangle()– DrawGeometry()– DrawImage() …
– A grafikai parancsok igazából nem rajzolnak, hanem csak tárolják/ megadják a kirajzolandó dolgokat (visszatartott módú grafikai rendszer)
– A Visualon belül Drawingok formájában vannak tárolva a rajzok (DrawingGroupban).
– A rajzolás időpontját a rendszer dönti el4
V 1.0 ÓE-NIK, 2014
Visual használat – 1. variáció• Minden Visual utódnak (így a grafikusfelület-elemeknek is)
vannak „vizuális gyermekei” (kirajzolandók)
• Új Visual objektumokat (pl. DrawingVisualokat) kell létrehozni és azokat elhelyezni a „vizuális gyermekek” között
• Kötelező felülírni az új Visualok „tulajdonosában” a VisualChildrenCount, GetVisualChild tulajdonságokat– VisualChildrenCount: adjuk vissza, hogy hány „vizuális gyermek” van.
– GetVisualChild: adjuk vissza az n. „vizuális gyermeket”.
• Lehetséges az új Visual objektumokat az objektumfákban is elhelyezni (AddVisualChild(), AddLogicalChild())– Események és találattesztelés támogatása miatt
5
V 1.0 ÓE-NIK, 2014
Visual használat 1. variáció példapublic partial class MainWindow : Window{ //sokszor nem a MainWindow-ban DrawingVisual visualChild; //csináljuk, hanem egy FrameworkElement public MainWindow() //utódot származtatunk és azt rakjuk { //a MainWindow-ra majd InitializeComponent(); visualChild = new DrawingVisual(); using (DrawingContext context = visualChild.RenderOpen()) { context.DrawEllipse(Brushes.Red, null, new Point(50, 50),10,10); } AddVisualChild(visualChild); AddLogicalChild(visualChild); } protected override int VisualChildrenCount { get { return base.VisualChildrenCount + 1; } } protected override Visual GetVisualChild(int index) { if (index < base.VisualChildrenCount) return base.GetVisualChild(index); else return visualChild; }
6
V 1.0 ÓE-NIK, 2014
Visual használat 2. variáció
• Kihasználjuk, hogy az ablak (vagy bármilyen más GUI elem) is Visual
• Amikor rajzolódik, az OnRender() metódusa hívódik– Ez felülírható, DrawingContext objektumot kap paraméterül, a
DrawingContext-en keresztül tudunk rajzolni a Visualra
• Új rajzolás mindig kikényszeríthető az InvalidateVisual() függvénnyel
class MainWindow : Window //tipikusan ezt sem a MainWindow-ban,{ //hanem pl. FrameworkElement utód... //... //- ablaknál Background=Transparent kell. protected override void OnRender(DrawingContext drawingContext) { drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Red, 2), geometry); }}
7
V 1.0 ÓE-NIK, 2014
Feladat – Asteroids
8
V 1.0 ÓE-NIK, 2014
• Asteroids szabályok:– Játékos csak foroghat és lőhet.– Az aszteroida véletlenszerű irányba egyenletesen mozog, ha a
képernyő szélére ér, visszatér a másik oldalon– Ha a játékos lövése eltalál egy aszteroidát, az eltűnik.
(Nehezebb verzió: két kisebb és gyorsabban mozgó részre válik szét, egy bizonyos mérethatárig.)
– Ha a játékos lövése a képernyő szélére ér, visszatér a másik oldalon. Viszont a lövés csak bizonyos ideig „él”, egy idő után eltűnik.
9
V 1.0 ÓE-NIK, 2014
Transzformációk
• Transform utódokkal reprezentálódnak (transzformációs mátrix)– Forgatás (RotateTransform)– Skálázás (ScaleTransform)– Nyújtás (SkewTransform)– Mozgatás (MoveTransform)– Általános transzformáció (MatrixTransform)– Több transzformáció egymás után (TransformGroup)
10
V 1.0 ÓE-NIK, 2014
Transzformáció alkalmazásai
• GUI-elemeken (FrameworkElement utódok):– LayoutTransform (kihelyezés előtt transzformál)– RenderTransform (kihelyezés után transzformál)
• Geometriákon:– Transform
• Figyelem: nem módosít koordinátákat!– A Transform-ot levéve (xxx.Transform = Transform.Identity) az
eredeti koordinátákon marad az objektum– Metszésnél esetleg gondot okoz
11
V 1.0 ÓE-NIK, 2014
Geometriák metszése (érintésvizsgálat)• Geometriák metsződésének vizsgálatához az
elmetszéssel létrejött új geometriát létre kell hozni (Geometry.Combine()), majd a területét vizsgálni (GetArea())
• Figyelem: LineGeometry-nak nincs kiterjedése, így a metszet területe 0 – Megoldása a vonal „kiterjesztésével”– geometry.GetWidenedPathGeometry(new Pen(Brushes.Blue, 2))
Geometry intersection = Geometry.Combine(geometry, otherGeometry, GeometryCombineMode.Intersect, null);
return intersection.GetArea() != 0;
12
V 1.0 ÓE-NIK, 2014
Feladat – Flappy Birds Turbo
13
V 1.0 ÓE-NIK, 2014
Megoldási alternatíva
• Minden játékelem Geometry típusú adattagja úgy kerül beállításra, hogy a középpont koordinátája (0;0) legyen
• Kirajzolás/ütközésvizsgálat előtt transzformáljuk a megfelelő pozícióba
TransformGroup tg = new TransformGroup();tg.Children.Add(new TranslateTransform(cx, cy));tg.Children.Add(new RotateTransform(degree, cx, cy));Geometry copy = area.Clone();copy.Transform = tg;return copy.GetFlattenedPathGeometry();
14
V 1.0 ÓE-NIK, 2014
Grafikai lehetőségek WPF-ben
15
Megközelítés Eseménykezelés / rajzolás vezérlése
Használat Objektumok száma
Shape Rajzolt objektumonként külön
XAML + Binding ~100
Drawing Hosztoló objektum kezeli, az összes rajzolt objektumot együtt
XAML + Binding + Converterek (xxx Geometry)
~1000
Visual Hosztoló objektum kezeli, egyedi kirajzoló metódus
CS kód: OnRender + DrawingContext + Geometry
~10000