Diskuze: C# - pomalé vykreslování?

C# .NET .NET (C# a Visual Basic) C# - pomalé vykreslování? American English version English version

Avatar
František Boháček:

Zdravím, mám takový problém, dělám aplikaci do školy a chtěl jsem si vše v ní nakreslit buď ve WF na PictureBox nebo ve WPF na Image.

Vyskytly se mi ale komplikace a potřebuji pomoc, vždy se mi to vykreslí za delší čas, třeba více jak 2 s, zkoušel jsem se přes debug podívat na to, kde to bere tolik času, ale docela bez úspěchu, protože nejsem v debugu zase takový znalec, nepohcopil jsem, proč mi to ukazovalo třeba na ukončené složené závorce 210 ms, takže jsem se nehnul z místa. Zkoušel jsem to už dost předělat, nejdříve jsem to měl na WPF, teď ve WF (s WPF nemám moc zkušeností a tak jsem to zkusil takto vyřešit, neúspěšně). Zkoušel jsem to udělat i přes eventy, ale nechápu, co jsem si od toho sliboval. :D

Kód mám rozdělen do několika tříd a jednoho rozhraní, všechno zde pošlu.

Omlouvám se, že jsou někde nějaké věci navíc (nepoužity), např. Dispatcher ve tříde MainTask, kde není vůbec použit, je to z důvodu, že jsem nejdříve PictureBoxu přiřazoval obrázek přes něj.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PercentagesPractise.ScreenObjects
{
    interface IScreenObject
    {
        bool isActive();
        void Draw(Graphics g);
        void _Update();
    }
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PercentagesPractise.ScreenObjects
{
    class ScreenObject : IScreenObject
    {
        //Click, Hover ...
        public EventHandler OnClick { get; set; }
        public EventHandler OnDoubleClick { get; set; }
        public EventHandler OnHover { get; set; }
        //Update
        public EventHandler BeforeUpdate { get; set; }
        public EventHandler Update { get; set; }
        public EventHandler AfterUpdate { get; set; }

        public bool isActivated { get; set; }

        public bool isActive()
        {
            return isActivated;
        }
        public bool Fill
        {
            get
            {
                return fill;
            }
            set
            {
                fill = value;
            }
        }

        public Color color;
        public Rectangle rectangle;
        public float width;
        public bool fill;

        public ScreenObject(Color color, Rectangle rectangle, bool fill = false, float width = 1)
        {
            BeforeUpdate += (sender, e) => { };
            Update += (sender, e) => { };
            AfterUpdate += (sender, e) => { };
            isActivated = true;
            this.color = color;
            this.rectangle = rectangle;
            this.width = width;
            this.fill = fill;
        }



        public virtual void _Update()
        {
            BeforeUpdate(null, null);
            Update(null, null);
            AfterUpdate(null, null);
        }

        public virtual void Draw(Graphics g)
        {

            if (fill)
                g.FillRectangle(new SolidBrush(color), rectangle.x, rectangle.y, rectangle.width, rectangle.height);
            else
            {
                Pen p = new Pen(color, width);
                g.DrawRectangle(p, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PercentagesPractise.ScreenObjects
{
    class Screen : IScreenObject
    {
        protected List<ScreenObject> objs { get; set; }
        public bool isActivated { get; set; }
        public Screen(List<ScreenObject> objs)
        {
            this.objs = objs;
            isActivated = true;
        }
        public bool isActive()
        {
            return isActivated;
        }
        public void Draw(Graphics g)
        {
           foreach(ScreenObject obj in objs)
            {
                obj.Draw(g);
            }
        }
        public void _Update()
        {
            foreach (ScreenObject obj in objs)
            {
                obj._Update();
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace PercentagesPractise.ScreenObjects
{
    class MainTask
    {
        public EventHandler<Bitmap> onDraw { get; set; }
        List<IScreenObject> activeObjects
        {
            get
            {
                List <IScreenObject> objs = new List<IScreenObject>(objects);
                if(objects != null)
                foreach(IScreenObject obj in objects)
                {
                    if (!obj.isActive())
                        objs.Remove(obj);
                }
                return objs;
            }
        }
        public bool IsRunning {
            get
            {
                return running;
            }
            set
            {
                if (value && !running)
                    Start();
                running = value;
            }
        }

        public int Width
        {
            get
            {
                return width;
            }
            set
            {
                width = value;
            }
        }

        public int Height
        {
            get
            {
                return height;
            }
            set
            {
                height = value;
            }
        }

        private List<IScreenObject> objects = new List<IScreenObject>();
        private Thread updater, drawer;
        private Dispatcher dis;
        private bool running;
        private int width, height;
        private System.Windows.Forms.PictureBox pb;
        public MainTask(List<IScreenObject> objs, Dispatcher dis, System.Windows.Forms.PictureBox pb)
        {
           // onDraw += (sender, e) => { };
            this.dis = dis;
            if(objs != null)
              objects = objs;
            this.pb = pb;
        }

        public void Start()
        {
            running = true;

            Bitmap b = new Bitmap(1920, 1024);
           // onDraw(null, b);
            Graphics g = Graphics.FromImage(b);
            drawer = new Thread(new ThreadStart(() => {

                while (running)
                {
                   // if (onDraw == null)
                   //     continue;

                    g.FillRectangle(Brushes.Gray, 0, 0, 1920, 1024);
                    foreach (IScreenObject obj in objects)
                    {
                        obj.Draw(g);
                    }
                    pb.Image = new Bitmap(b, new System.Drawing.Size(width, height));
                    //onDraw(null, );
                }
            }));
            updater = new Thread(new ThreadStart(() =>
            {
                while (running)
                {
                    foreach (IScreenObject obj in activeObjects)
                    {
                        obj._Update();
                    }
                }
            }));
            updater.Start();
            drawer.Start();


        }
        public void Clicked(PointF pos)
        {
            MessageBox.Show("CLICKED! " + pos.X + " " + pos.Y);
        }

    }
}
using PercentagesPractise.ScreenObjects;
using PercentagesPractise.ScreenObjects.AddonFunctions;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PercentagesPractise.Screens
{
    class MainScreen : Screen
    {
        public MainScreen() : base(null)
        {
            List<ScreenObject> objs = new List<ScreenObject>();

            //Background
            ScreenObjects.Rectangle bcg = new ScreenObjects.Rectangle(0, 0, 1920, 1080);
            ScreenObject bcgso = new ScreenObject(Color.Black, bcg, true);
            //objs.Add(bcgso);


            ScreenObjects.Rectangle rct = new ScreenObjects.Rectangle(500, 500, 20, 20);
            ScreenObject obj = new ScreenObject(Color.Blue, rct, true);
            Random r = new Random();
            Vector v = new Vector(20f, 20f);
            obj.Update += (sender, e) => {

                if (obj.rectangle.x < 0 || obj.rectangle.x > 1920)
                    v.x = -v.x;
                if (obj.rectangle.y < 0 || obj.rectangle.y > 1024)
                    v.y = -v.y;

                obj.rectangle.x += v.x;
                obj.rectangle.y += v.y;
            };
            bcgso.isActivated = false;
            objs.Add(obj);


            this.objs = objs;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PercentagesPractise.ScreenObjects.AddonFunctions
{
    class Vector
    {


        public float x { get; set; }
        public float y { get; set; }

        public Vector(float xy)
        {
            x = y = xy;
        }
        public Vector(float x, float y)
        {
            this.x = x;
            this.y = y;
        }
        public Vector()
        {

        }

        public void Reverse()
        {
            x = -x;
            y = -y;
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PercentagesPractise.ScreenObjects
{
    struct Rectangle
    {
        public float x, y;
        public float width, height;

        public Rectangle(float x, float y, float width, float height)
        {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }
    }
}

Tohle mám ve třídě WP.

private void app_Load(object sender, EventArgs e)
{
    List<IScreenObject> se = new List<IScreenObject>();
    ScreenObjects.Screen scr = new MainScreen();
    se.Add(scr);
    MainTask t = new MainTask(se, Dispatcher.CurrentDispatcher, image);
    t.Width = image.Width;
    t.Height = image.Height;
    t.Start();
}

Děkuji všem, kteří se alespoň na kód podívají.

Pokud byste chtěli cokoliv více z kódu, jsem ochotný to poskytnout, ale myslím, že to nebude potřeba

 
Odpovědět 15.11.2015 17:09
Avatar
František Boháček:

Problém vyřešen, pomohli mi jinde.

Bylo to tím, že jsem to vykresloval nejděíve do Bitmapy a pak až dával do PictureBoxu.
Vyřešil jsem to tak, že jako Graphics jsem vzal Graphics z pictureBox.Cre­ateGraphics().

 
Nahoru Odpovědět 16.11.2015 17:02
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.