Laden...

GUI beschleunigen

Erstellt von Bow vor 14 Jahren Letzter Beitrag vor 14 Jahren 3.435 Views
B
Bow Themenstarter:in
34 Beiträge seit 2009
vor 14 Jahren
GUI beschleunigen

Hallo

Habe ein Programm geschrieben mit dem man ziemlich viele Elemente auf einmal anzeigen, verschieben oder sonst wie bearbeiten kann. Leider wird das so ab 4000 Elementen ziemlich langsam.

Kann man das irgendwie beschleunigen? Machen hier Threads Sinn??
hier mein onPaintCode:


public void Draw(Graphics g)
{
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    foreach (Connection c in this.ConnectionList)
    {   
        if (c.Selected)
        {
            g.DrawLine(linePenSelection, c.D1.GetConnectionPoint(c), c.D2.GetConnectionPoint(c));
        }
        g.DrawLine(linePen, c.D1.GetConnectionPoint(c), c.D2.GetConnectionPoint(c));
        c.draw(g, FontConnectionID);
    }

    
    foreach (Connection c in this.TempConnectionBufferList)
    {
        g.DrawLine(linePenSelection, c.D1.GetConnectionPoint(c), c.D2.GetConnectionPoint(c));
        g.DrawLine(linePen, c.D1.GetConnectionPoint(c), c.D2.GetConnectionPoint(c));
    }

    foreach (Connection c in this.ConnectionBufferList)
    {
        g.DrawLine(linePenSelection, c.D1.GetConnectionPoint(c), c.D2.GetConnectionPoint(c));
        g.DrawLine(linePen, c.D1.GetConnectionPoint(c), c.D2.GetConnectionPoint(c));
    }

    foreach (Device d in this)
    {
        if (!d.Selected)
        {   //mark devices
            d.SetResolution(g.DpiX, g.DpiY);
            g.DrawImageUnscaled(d.Symbol, d.Position);                   
        }
    }

    foreach (Device d in this)
    {
        if (d.Selected)
        {   
            d.SetResolution(g.DpiX, g.DpiY);
            g.DrawImageUnscaled(d.Symbol, d.Position);
            g.DrawRectangle(myPen, d.PositionX, d.PositionY, d.Symbol.Width, d.Symbol.Height);
        }
    }
    foreach (Device d in DeviceBufferList)
    {
        if (d.Selected)
        {   
            d.SetResolution(g.DpiX, g.DpiY);
            g.DrawImageUnscaled(d.Symbol, d.Position);
            g.DrawRectangle(myPen, d.PositionX, d.PositionY, d.Symbol.Width, d.Symbol.Height);
        }
    }
    foreach (int i in DeviceIndexBufferList)
    {   //Draw SelectionSet
        this[i].SetResolution(g.DpiX, g.DpiY);
        g.DrawImageUnscaled(this[i].Symbol, this[i].Position);
        g.DrawRectangle(myPen, this[i].PositionX, this[i].PositionY, this[i].Symbol.Width, this[i].Symbol.Height);
    }
}

Vielleicht kann man ja schon direkt am Code was machen?

Ps.: Ich speichere die Icons in kleinen Bitmaps ab. Das heißt jedes Objekt hat auch ein Bitmap gespeichert (im Konstruktor wird das Bild gezeichnet). Ist es schneller die Bitmpas anzuzeigen oder alle Bilder dauernd neu zu zeichnen?

D
496 Beiträge seit 2005
vor 14 Jahren

alter schwede! mal nur so aus neugier, was ist der sinn des ganzen?

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

R
164 Beiträge seit 2008
vor 14 Jahren

Es scheint, als ob die gesamte Oberfläche bei jedem OnPaint-Event neu gezeichnet wird. Das verschlingt natürlich viele Resourcen. Die EventArgs der OnPaint-Methode enthalten die Eigenschaft "ClipRectangle". Das ist der Bereich, der neu gezeichnet werden muss.

Es ist sehr wichtig, dass nur die Fläche neu gezeichnet werden darf, die in ClipRectangle angegeben ist. Außerdem kann man bei der Form DoubleBuffered auf true setzen, damit sie beim Zeichnen nicht flackert. Vielleicht hilft dir [FAQ] Flackernde Controls vermeiden / Schnelles, flackerfreies Zeichnen.
Überdenke eventuell die Speicherung der Daten und wähle eine speichersparende Lösung. Man kann dazu die Programme auch mit Profilern ausführen.

6.911 Beiträge seit 2009
vor 14 Jahren

Hallo Bow,

wie hast du das GIF erstellt? Scheint eine coole Sache zu sein.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

F
240 Beiträge seit 2006
vor 14 Jahren

Ich denke, GDI+ wird hier einfach an die Grenzen stoßen, wenn es tatsächlich alles neugezeichnet werden muss. Da wäre WPF wohl angemessener...

K
133 Beiträge seit 2009
vor 14 Jahren

Ich denke, GDI+ wird hier einfach an die Grenzen stoßen, wenn es tatsächlich alles neugezeichnet werden muss. Da wäre WPF wohl angemessener...

Stößt definitive an die Grenzen ^^. Könntest aber auch mit XNA arbeiten... ist auch ziemlich einfach!

1.002 Beiträge seit 2007
vor 14 Jahren

Hallo Bow,

wie hast du das GIF erstellt?

das würde mich auch interessieren 😃.
Gerade für Tutorials ist das ja sehr praktisch ...

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

3.430 Beiträge seit 2007
vor 14 Jahren

alter schwede! mal nur so aus neugier, was ist der sinn des ganzen?

Und noch ne Frage.... Wer kann den sowas bedienen.
Wenn ich denke ich müsste 4000Element auf einen Fenster anordnen oder was auch immer wird mir schon schlecht.

Und ja, WPF wäre dafür sicherlich besser geeignet.
Denn die Shapes kannst du da einfach so verschieben und musst nicht jedes mal alles neu zeichnen.

Gruss
Michael

B
Bow Themenstarter:in
34 Beiträge seit 2009
vor 14 Jahren

Hallo!

Danke für die zahlreichen Antworten. (Sinn des ganzen ist es eine GUI zu schreiben zum erstellen von Netzwerksimulationen in omnetpp. Normalerweise muss man da mühselig per Hand Text schreiben welcher das Netzwerk repräsentiert. und ich will das automatisieren. Als Angabe habe ich bekommen dass meine Simulation ca.: 65000 Geräte beherrschen muss.

Hat jemand schon mal Autocad bedient, da kann man auch viele so um die 100000 Objekte und mehr auf einmal verschieben kopieren oder sonst was damit anstellen. Würde gerne wissen wie die das machen?

Also DoubleBuffered verwende ich schon von Anfang an!
ClipRectangle wird mir nicht viel bringen da ich schon so eine ähnlich Abfrage drinnen habe. Nämlich wenn ein Objekt eine negative Koordinate hat dann zeichne ich es gar nicht.
ps.: Was meinst du (rechner) mit speichersparende Lösung? Meinst du dass ich nicht in jedem Objekt ein Bild speichern sollte?

Bezüglich WPF habe ich keine Erfahrung und Ahnung. Aber ist das wirklich so dass das Zeug schneller ist als GDI und WinForm, wenn ja warum ist das eigentlich so??

Bei WPF denke ich zu allererst an XML weil ich mal gehört habe das man bei WPF alles per XML anordnen kann und irgendwie habe ich daher das ganze noch nicht angeschaut. Obwohl nach euren Kommentaren hört sich das interessant an
Funktioniert eigentlich WPF unter WinXP?

ps.: Gif wurde mit CamtasiaStudio erstellt.

1.130 Beiträge seit 2007
vor 14 Jahren

da kann man auch viele so um die 100000 Objekte und mehr auf einmal verschieben kopieren oder sonst was damit anstellen.

Bei der Menge an elementen ist selbst der Aufruf von DrwaPrimitives (Directx) für jedes einzelne Element zuviel. Du kannst höchstens Directx nehmen, und mehrere Elemnente in einem vertexbuffer zusammenfassen oder elle Elemente einmal auf eine textur rendern und diese dann verschieben. Du brauchst aber zusätzlich noch eine Möglichkeit, nicht sichtbare Elemente herauszufiltern.

Das wird also kompliziert. Ab Directx 10 oder 11 🤔 solls ja hardware instancing geben. Das wäre eine möglichkeit, mit der ich mich ned so auskenne.

mindestens 100x schneller als gdi und mindestens 50x komplizierter wirds mit einer der beiden Techniken aber allemal. WPF Ist auch sehrviel schneller als gdi, hat aber im Vergleich zu direkter Nutzung von directx viel Overhead und man kann längst nicht sogut optimieren.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

6.862 Beiträge seit 2003
vor 14 Jahren

Hallo,

bezüglich WPF:
Die kurze Antwort ist, dass WPF auf DirectX zum Rendern setzt und daher hardwarebeschleunigt durch die GPU ist. Die lange Antwort würde auch noch die Ausnahmen und die grundsätzlich verschiedenen Zeichenphilosophien von WPF und GDI+ enthalten.

XML wird in Form von XAML zur Beschreibung der GUI verwendet, aber man wird nicht darauf beschränkt. Das was man in XAML beschreibt, kann man auch ohne weiteres in Code machen. WPF funktioniert auch problemlos unter XP, auch wenn es kleine Unterschiede zu späteren Betriebssystemen wie Vista und Windows 7 gibt.

Von daher ist es wesentlich leichter mit WPF komplexere GUIs zu basteln die auch bei vielen Elementen schnell ist. Aber, man muss WPF und das Zeichensystem genau kennen sonst kann man auch dort mächtig daneben greifen. Wenn man versucht die gleiche Logik wie in Windows Forms umzusetzen, hat man meist schon verloren. Deshalb muss man beim Wechsel mit ne ganzen Weile Einarbeitung rechnen. So auf die schnelle ist ein Umstieg daher nicht drin wenn man sich vorher noch nicht mit WPF beschäftigt hat.

Baka wa shinanakya naoranai.

Mein XING Profil.

5.299 Beiträge seit 2008
vor 14 Jahren

Das Problem ist doch, dass endlos Objekte gemalt werden, die von anderen Objekten dann wieder übermalt werden.
Wenn du also wasweißich, eine Fläche von 44 cm herumdraggst, wird die vlt 20 mal übereinander gemalt, und entspricht damit etwa 88, und ist langsam.
Weiß nicht, ob das Problem in Wpf anders ist.

In WinForm könnteste bei Mehrfach-Auswahl ein Bild der Fläche erstellen, und das herumdraggen.

Das wird sicher auch nicht einfach zu implementieren, aber wäre immerhin ein Ansatz.

Der frühe Apfel fängt den Wurm.