IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

0. Diel WPF - Rýchlosť vykresľovanie

V minulej lekcii, Hrianok notifikácia v C # .NET WPF , sme sa naučili tvoriť hrianok notifikácia.

Ahoj, rozhodol som sa začať s tutoriály pre WPF, pretože mi príde, že je pokročilejší ako Windows Forms, aspoň pokiaľ ide o vykresľovanie. Je tomu preto, že vo WPF sa už nepoužíva GDI a jeho systém spracovania grafiky v procesore, ale sa využíva DirectX3D, čo je bezpochyby veľká výhoda. Už nedochádza k preblikávania pri aktualizácii okna. Ak ste nikdy nerobili vo Windows Forms, tak tieto tutoriály nejspíš moc nepochopíte, pretože tu budem veľa porovnávať WF a WPF a popisovať rozdiely a ako prejsť z WF na WPF.

WPF síce používa jazyk C# rovnako ako WF, ale líšia sa tým, že na nastylování okná používa jazyk XAML, ktorý je podobný HTML kódu.

Jeho najväčšia prednosť vám ukážem na jednoduchom prográmku, ktorý som si nazval pre názornosť HalfHeight ktorý si vytvorím zároveň vo WF i vo WPF.

V tomto "programe" sa nám bude pohybovať obdĺžnik, ktorý zaberá celý form na šírku a polku na výšku. Bude sa pohybovať hore a dole, tým môžeme sledovať rýchlosť vykresľovania.

Zdrojový kód hlavného formu HalfHeight vo WF:

{
    public partial class Form1 : Form
    {
        // základní graphics formu
        Graphics g;

        // vedlejší graphics který neuvidíme
        Graphics tempGraphics;

        // bitmapa pro vytvoření vedlejších graphics
        Bitmap tempBitmap;

        // čas poslední snímku
        DateTime lastFrame;

        // obdelník pro zkoušku vykreslování
        Rectangle rectangle;

        // štětec s barvou
        SolidBrush brush = new SolidBrush(Color.Red);

        // proměnná zjištující pohyb obdelníku směrem dolů
        bool IsRectangleMovingDown = true;

        public Form1()
        {
            InitializeComponent();

            // vytvoří graphics hlavního formu
            g = this.CreateGraphics();

            // nastaví proměnou DateTime na teď
            lastFrame = DateTime.Now;

            // vytvoří nový timer
            Timer t = new Timer();

            // nastaví timer aby se spouštěl každou milisekundu (bude se spouštět méně často, ale menší hodnotu nastavit nelze)
            t.Interval = 33;

            // přidá event k timeru
            t.Tick += new EventHandler(t_Tick);

            // spustí timer
            t.Start();
        }

        protected override void OnLoad(EventArgs e)
        {
            // vytvoří novou bitmapu s velikostí okna
            tempBitmap = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);

            // vytvoří vedlejší graphics podle bitmapy
            tempGraphics = Graphics.FromImage(tempBitmap);

            // deklaruje nový obdelník
            rectangle = new Rectangle(0, 0, this.ClientSize.Width, this.ClientSize.Height / 2);
        }

        void t_Tick(object sender, EventArgs e)
        {
            // vyčistí vedlejší graphics
            tempGraphics.Clear(Color.White);

            // vykreslí obdelník do vedlejších graphics
            tempGraphics.FillRectangle(brush, rectangle);

            // vykreslí vedlejší graphics do formu
            g.DrawImage(tempBitmap, Point.Empty);

            // pohyb obdelníku nahoru a dolů
            if (IsRectangleMovingDown)
            {
                if (rectangle.Y < this.ClientSize.Height / 2)
                {
                    rectangle = new Rectangle(rectangle.X, rectangle.Y + 25, rectangle.Width, rectangle.Height);
                }
                else
                {
                    IsRectangleMovingDown = false;
                }
            }
            else
            {
                if (rectangle.Y > 0)
                {
                    rectangle = new Rectangle(rectangle.X, rectangle.Y - 25, rectangle.Width, rectangle.Height);
                }
                else
                {
                    IsRectangleMovingDown = true;
                }
            }

            // přepočítání času
            TimeSpan elapsed = DateTime.Now - lastFrame;

            // zobrazí počet uplynulých ms od posledního updatu
            label1.Text = elapsed.TotalMilliseconds.ToString();

            // zapsání nového času
            lastFrame = DateTime.Now;
        }
    }
}

Zdrojový kód hlavného formu HalfHeight vo WPF:

XAML časť:

<Window x:Class="HalfHeight_WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" WindowState="Maximized" Loaded="Window_Loaded">
    <Grid Name="grid">
        <Rectangle HorizontalAlignment="Left" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Fill="Red" Width="100" Height="100" />
        <TextBlock HorizontalAlignment="Left" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Background="Gray" Margin="12,12,0,0" />
    </Grid>
</Window>

C# časť:

{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        bool IsRectangleMovingDown = true;

        DateTime lastFrame;

        public MainWindow()
        {
            InitializeComponent();

            lastFrame = DateTime.Now;

            DispatcherTimer t = new DispatcherTimer();
            t.Interval = TimeSpan.FromMilliseconds(1);
            t.Tick += new EventHandler(t_Tick);
            t.Start();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            rectangle1.Width = grid.ActualWidth;
            rectangle1.Height = grid.ActualHeight / 2;
        }

        void t_Tick(object sender, EventArgs e)
        {
            if (IsRectangleMovingDown)
            {
                if (rectangle1.Margin.Top < grid.ActualHeight / 2d)
                {
                    rectangle1.Margin = new Thickness(rectangle1.Margin.Left, rectangle1.Margin.Top + 25, 0, 0);
                }
                else
                {
                    IsRectangleMovingDown = false;
                }
            }
            else
            {
                if (rectangle1.Margin.Top > 0)
                {
                    rectangle1.Margin = new Thickness(rectangle1.Margin.Left, rectangle1.Margin.Top - 25, 0, 0);
                }
                else
                {
                    IsRectangleMovingDown = true;
                }
            }

            TimeSpan elapsed = DateTime.Now - lastFrame;
            textBlock1.Text = elapsed.TotalMilliseconds.ToString();

            lastFrame = DateTime.Now;
        }
    }
}

Nákupný

Na mojom počítači sa mi ukazoval vo WF čas od posledného obrázka 90 - 110 ms (cca 10 FPS) a vo WPF 10 - 20 ms (cca 50 - 100 FPS).

Vo WF tam bol vidieť jasne trhaný pohyb, zatiaľ čo vo WPF nebol vidieť jediný zásek.

Dúfam, že to postačí ako dôkaz ako rýchlo je WPF schopné vykresľovať narozdiel od WF, zdrojové kódy HalfHeight vo WF aj WPF budú priložené.

V budúcom dieli si ukážeme základné kontrolky WPF.


 

Predchádzajúci článok
Hrianok notifikácia v C # .NET WPF
Všetky články v sekcii
Okenné aplikácie v C # .NET WPF
Článok pre vás napísal Theodor Johnson
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor má většinou na svědomí projekty v jazyce C#.
Aktivity