• Nem Talált Eredményt

Software engineering and GUI design

N/A
N/A
Protected

Academic year: 2023

Ossza meg "Software engineering and GUI design"

Copied!
40
0
0

Teljes szövegt

(1)

Software engineering and GUI design

WPF graphics intro

Usage of the FrameworkElement class

(2)

WPF graphics – coordinate system

The (0,0) point is in the top-left corner, so every location is the position of the top-left corner based on the top-left corner of the container

– An object’s final location is affected by many properties:

HorizontalAlignment, Margin, Padding, layout manager settings,

– Taking all factors into account, there is a separate phase

(“Layout”) that determines the final 2D position – not trivial to read, very hard to write!

(3)

WPF graphics – types

(System.Windows)

Nothing is displayed, these types are only used for data representation!

Struct types (value types)

Point: a single point in 2D space – X, Y

Size

– Width, Height

Rect, Int32Rect: a rectangle in 2D space

– X, Y, Width, Height, Top, Bottom, Left, Right

Vector: a location vector in 2D space – X, Y, Length, LengthSquared

(4)

WPF graphics – colors

• Every color is represented with four 8bit values:

Red (R), Green (G), Blue (B) – bytes (0-255), so totally 256^3 ≈ 16 million colors are possible (“good enough”)

Alpha (A) – Defines the transparency of the color, 0: fully transparent, 255: not transparent

• The Color struct is used to represent colors

Color color = Colors.Red;

Color color = Color.FromArgb(20, 255, 0, 0);

(5)

WPF graphics – brushes

(6)

WPF graphics – brushes

C# definition:

XAML definition:

//pre-defined solid color brush:

button.Background = Brushes.Red;

//self-made brush with pre-defined color:

button.Background = new SolidColorBrush(Colors.Aqua);

//self-made brush with self-made color:

Color almostRed = Color.FromArgb(20, 255, 0, 0);

button.Background = new SolidColorBrush(almostRed);

<Button Background="AliceBlue" Content="Button" .../>

<Button Background="#FFFF0000" Content="Button2" .../>

<Grid.Resources>

<SolidColorBrush x:Key="myColor" Color="Azure"/>

</Grid.Resources>

...

<Button Background="{StaticResource myColor}"></Button>

(7)

WPF graphics – other types

Pen

– Used for drawing lines

– Fill (brush), thickness, line style, line endings

Geometry

– Can represent an arbitrary geometrical shape (abstract class) – The descendants are used

– System.Windows.Rect vs

System.Windows.Media.RectangleGeometry vs System.Windows.Shapes.Rectangle

– Universal geometrical operations, even with very complex

geometrical shapes (e.g. we can create geometry from letters, union/intersection, splines, etc…)

(8)

Other geometry types

EllipseGeometry ellipse = new EllipseGeometry(new Point(10, 10), 10, 10);

FormattedText text = new FormattedText("This is my ellipse.",

CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Tahoma"), 16, Brushes.Black);

Geometry textGeometry =

text.BuildGeometry(new Point(10, 20));

GeometryGroup group = new GeometryGroup();

group.Children.Add(ellipse);

group.Children.Add(textGeometry);

StreamGeometry = polygons

PathGeometry = set of complex line segments

– From text, using FormattedText.BuildGeometry(xxx) method

Handle multiple Geometry instances with GeometryGroup

– The GeometryGroup is a Geometry descendant, so it is very easy to handle with complex geometric shapes

8

(9)

UI element to display images: Image

Image.Source: the image to be displayed

– Descendants of System.Windows.Media.ImageSource class

Image.Stretch  automatic resize (None, Fill, Uniform, UniformToFill)

D3DImage DrawingImage

BitmapSource (+descendants)

abcdef

(10)

Graphics possibilities in WPF

Shapes (System.Windows.Shapes.Shape descendants) – Pre-made, simple controls

– Also accessible via the Toolbox (Rectangle, Ellipse...)

– Input, focus, events, data binding: to be handled individually…

– Only if few (max ~100) objects are used

Drawings (System.Windows.Media.Drawing descendants)

– Cannot be used on their own, must be put into a hosting object ( Image.Source = new DrawingImage(xxx) )

– No support for input events, the hosting object handles its own events

– Also usable from XAML, with a few data bindings and converters – Faster than the Shape controls (max ~1000 objects)

Visuals (System.Windows.Media.Visual descendants)

– The most complex, also the fastest (max ~10000 drawn objects) – Drawn objects  no need to be stored in the memory

– Always handled from code  hard to write pretty code!

(11)

Graphics possibilities in WPF

Approach Event handling /

Display handling Usage Number of

objects Shape Drawn object =

control, individually for every controls

XAML + Binding ~100

Drawing Hosting object (image) handles all drawn

objects together

XAML + Binding + Converters

(xxx  Drawing)

~1000

Visual Hosting object displays the drawn objects

together, no real object storage, only used as a “drawing canvas”

CS code:

OnRender +

DrawingContext + Geometry

~10000

(12)

Usage of Visual descendants

Typically we do this not in a Window, but rather in a unique FrameworkElement descendant

– Using the OnRender() method we can issue drawing commands – DrawingContext  the drawing canvas that we draw upon

– Not an immediate operation (retained mode)

Refresh of the control can always be enforced using the

InvalidateVisual() method  which MUST NEVER be called from the OnRender method

class MainWindow : Window // window, we need Background=Transparent

{

protected override void OnRender(DrawingContext drawingContext)

{

drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Red, 2), geometry);

} }

(13)

FrameworkElement rules

Empty (not drawn) areas will not fire the mouse events

– The first drawn object should be a big background rectangle

Keyboard events are not captured

– The window will capture them, and we can always access the window using Window.GetWindow(this) (not elegant, but this semester it is good enough for us)

– OR: Focusable=true and the control will also capture the keyboard events (if it has the keyboard focus!)

Try and use it in a nicely layered way

– It is very easy to write hard-to-maintain code – Aim: Model + Logic + Control

Home-practice exercises: at the end of this presentation

(14)

Accessing UI elements from multiple threads

In Windows, UI elements (controls) can typically only be accessed from the creator thread (GUI thread, UI thread)

– That includes indirect access

– Few exceptions (some methods, PropertyChanged event)

Universal solution: Invoke

– Ask a callback from the UI thread (Blocking! Deadlock danger!)

Dispatcher.Invoke(() =>

{

label.Content = ...;

listBox.Items.Add(...);

});

Using Task: alternative Task scheduler – Default: Thread Pool Task Scheduler

– It is possible to assign new tasks to the GUI-thread scheduler

(15)

Accessing UI elements from multiple threads

GUI task scheduler

– Obtain reference from the GUI thread

– TaskScheduler.FromCurrentSynchronizationContext()

Task<int> taskWithReturnValue =

Task.Run(() => { Thread.Sleep(1000); return 6; });

taskWithReturnValue.ContinueWith(

t => textBox1.Text = "Result: " + t.Result, CancellationToken.None,

TaskContinuationOptions.OnlyOnRanToCompletion,

TaskScheduler.FromCurrentSynchronizationContext());

(16)

System.Windows.Threading.Dispatch erTimer

We use it to execute operations periodically (GameLogic,

automatic actions)

– Interval: property to set how often the timer will be executed (TimeSpan type)

– Start(), Stop(): Methods

– Tick: Event that signals that the specified interval is over (with the event, the measurement of the interval re-starts)

Many different Timer types – do not mix them up!

System.Timers.Timer  Threadsafe, very precise

System.Threading.Timer  Uses a Threadpool thread, not threadsafe System.Windows.Forms.Timer  Windows forms component

System.Web.UI.Timer  Periodic webpage postback (synchronized or async)

System.Windows.Threading.DispatcherTimer  WPF threadsafe timer that uses the DispatcherThread

(17)

Lesson Exercise: Pong

(18)

Flappy Bird

(19)

Transformations

Represented using Transform descendants (they are matrices) – RotateTransform

– ScaleTransform – SkewTransform

– Move (TranslateTransform)

– Universal transformations (MatrixTransform)

– Multiple transformations after each other (TransformGroup)

(20)

Using transformations

FrameworkElement + Layout manager (Grid, StackPanel…) – LayoutTransform (before the layout phase)

– RenderTransform (after the layout phase)

Geometry

– Geometry geo = new RectangleGeometry(xxx);

– geo.Transform = new xxxTransform(xxx);

– Warning: doesn’t modify the original geometry coordinates – Geometry result = geo.GetFlattenedPathGeometry()

– Erase transformation: geo.Transform = Transform.Identity;

DrawingContext

– DrawingContext.PushTransform(new TranslateTransform(xxx));

– DrawingContext.DrawXXX(xxx);

– DrawingContext.Pop();

(21)

Using transformations (in our games)

We should set every gameitem’s Geometry datafield to make them centered around (0;0)

Then before draw/collision detection, we transform them into the appropriate position/orientation

Slower (due to the continuous re-calculation), but makes modeling/programming a lot easier

(22)

Intersection of geometries (collision detection)

To check for collisions, we have to create a new geometry from the intersection of the two geometries (Geometry.Combine()), and then calculate surface area (GetArea())

Warning: LineGeometry has no surface area, so the combined geometry will always have a surface area of zero

– Solvable by „extending” the line – Geometry result =

geometry.GetWidenedPathGeometry(new Pen(Brushes.Blue, 2))

– The color of the pen is not used, only the line style/thickness

Geometry intersection = Geometry.Combine(geometry,

otherGeometry, GeometryCombineMode.Intersect, null);

return intersection.GetArea() != 0;

(23)

Lesson exercise: Flappy Birds Turbo

(24)

Class Bird : GameItem

(25)

Class Pipe : GameItem

(26)

Lesson exercise: Laby the Ultimate

Labyrinth

(27)

Single-responsibility classes

Combine the previously known solutions AND – Attaching resources (file-s, do not overuse!) – Load images: BMP/PNG/JPG  ImageBrush

– Tiled Brush: for drawing walls, Tile vs Pixel coordinates – More efficient render process

Builder Design Pattern

Saving the ImageBrush instances into a Dictionary

Saving the Drawing (Brush + Pen + Geometry) instances into variables

– Mouse clicks only work on drawn areas  big background image

– Subscribe to the KeyDown event of the owner window – Refresh the GameControl

(28)

Tiled brush?

(29)

Creating a self-made control

Can be used from XAML the usual way – Zero-parameter constructor must exist

Inheritance: from FrameworkElement base class – All our games beforehand were in fact, controls

– Using the same rules, we can create a normally usable control that won’t fill up the whole window, and fits into the layout – Subscription to window events / MessageBox is not elegant

Inheritance: from arbitrary control as a base class

– Extend a pre-existing control with extra functionality

Composition: User control

– Create new control by assembling pre-existing controls

(30)

Accessing properties from XAML

Properties/events can be accessed the usual way – <local:UpDownControl IsDown="True"

IsDownChanged="UpDownControl_IsDownChanged„

Data binding: IsDown="{Binding Path=PointsDown}"

– Data binding WILL NOT work with simple properties – It uses “Dependency Property” properties

– If you want a bool-typed Dependency property, it can be described as a global storage similar to

public static Dictionary<UpDownControl, bool> IsDownProperty public bool IsDown

{

get { return IsDownProperty[this]; } set { IsDownProperty[this] = value; } }

(31)

Dependency Property

public static readonly DependencyProperty IsDownProperty =

DependencyProperty.Register(xxx);

public bool IsDown {

get { return (bool)GetValue(IsDownProperty);

}

set { SetValue(IsDownProperty, value); } }

DependencyProperty.Register(

nameof(IsDown), typeof(bool), typeof(UpDownControl),

(32)

Lesson exercise: UpDownControl +

SortedLB

(33)

Software engineering and GUI design

Practice exercises

(34)

Home practice: SimpleLaby

(35)

Home practice: SimpleLaby

If the player finishes a level, a new one should be automatically loaded

We should measure the time for every level (System.Diagnostics.Stopwatch class)

In a new window, display the level times using a Graph

drawn using a GeometryDrawing

(36)

Home practice: Asteroids

(37)

Home practice: Asteroids

Asteroids rules:

– The player can only rotate and shoot.

– The asteroid moves in a random direction using a constant speed, when it hits the side of the gamescreen, it re-appears on the other side

– If the bullet hits an asteroid, it disappears (real version: it splits up into smaller asteroids)

– The bullet also re-appears on the other side of the gamescreen (but the bullet is only “alive” for a given amount of time)

(38)

Home practice: Chaos Frogger

(39)

Home practice: Chaos Frogger

A single obstacle can only move in the up-down OR in the left-right directions. If they reach the side of the window, they reverse

Their speed changes randomly, and also there are some evil obstacles that speed up if the player is nearby

The player has three lives at the beginning, and we have

to get to the bottom-right corner. If an obstacle touches

the player, then the player loses a life.

(40)

Home practice: Tic Tac Toe

– Rules: the players take turns in putting down their respective

marks. The one who makes up three items horizontally, vertically or diagonally will win the game

– If the playing field fills up without a win, then it’s a tie

Hivatkozások

KAPCSOLÓDÓ DOKUMENTUMOK

This menu provides access to the standard window options (docking, closing, and floating in the main window) and to the Plot window features described in the following

Ennek eredménye azután az, hogy a Holland Nemzeti Könyvtár a hollandiai webtér teljes anya- gának csupán 0,14%-át tudja begy ű jteni, illetve feldolgozni.. A

Az új kötelespéldány törvény szerint amennyiben a könyvtár nem tudja learatni a gyűjtőkörbe eső tar- talmat, akkor a tartalom tulajdonosa kötelezett arra, hogy eljuttassa azt

● jól konfigurált robots.txt, amely beengedi a robo- tokat, de csak a tényleges tartalmat szolgáltató, illetve számukra optimalizált részekre. A robotbarát webhelyek

In the Kernel window, you can add, modify, and delete kernel compo- nents: System, Thread Types, Boot Threads, Round-Robin Proper- ties, Semaphores, Event Bits, Events, Interrupts,

Disassembly, Editor, Output Windows: Load dotprodc.dxe By default, VisualDSP++ opens an Output window, a Disassembly window, and an Editor window that displays the source file

Trapezoidal window showed much better resistance in 3-point bending and axial loadings compared to other window geometries, while it showed the weaker performance in torsional

Rheological measurements were performed by shearing the suspension at constant shear stress (5 Pa) both in lack of electric field and under the influence of field. Low oscillating