Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
1
Ismétlés (Grafikai lehetőségek WPF-ben)
Programozás III. Ismétlés (Grafikai lehetőségek WPF-ben) Visual utódok TODO: Üres területre nem lehet kattintani, billentyűzet csak ablakhoz rendelhető VAGY Focusable=true és fókuszálni kell
2
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 objektumig) XAML lehetőségek korlátozottak, mindig kódból kezeljük
3
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
4
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 el The DrawingContext allows you to populate a Visual with visual content. When you use a DrawingContext object's draw commands, you are actually storing a set of render data that will later be used by the graphics you are not drawing to the screen in real-time. DrawingGroup.Open and DrawingVisual.RenderOpen. Ezekkel lehet DrawingContextet nyerni. A Visual describes its content as one or more Drawing objects contained within a DrawingGroup
5
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
6
Visual használat 1. variáció példa
public 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;
7
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); } Ez a megoldás egyszerűbb, de a másikat szokták alkalmazni egyébként.
8
Feladat – Asteroids
9
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.
10
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)
11
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
12
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;
13
Feladat – Flappy Birds Turbo
14
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();
15
Grafikai lehetőségek WPF-ben
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
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.