| Autor |
Beitrag |
mkRE
      
Beiträge: 98
|
Verfasst: Fr 06.11.15 23:07
Hallo zusammen,
ich wende mich an euch weil ich gerade verzweifelt an einer kniffligen Aufgabe arbeite.
Ich suche nach einer Lösung die folgenden Formen in einer Anwendung einzuzeichen und dann noch Größentechnisch verändern zu können mittels eines TrackBar.
Hat jemand von euch Erfahrung damit allgemein Grafics animiert größenveränderlich zu machen?
Und hat jemand schon so eine Art Form gezeichnet im Code?
Siehe Anhang:
Vielen Dank
Einloggen, um Attachments anzusehen!
|
|
Th69
      

Beiträge: 4805
Erhaltene Danke: 1061
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 07.11.15 08:47
Hallo,
wie weit ist denn bisher dein Kenntnisstand bzgl. Zeichnen in Forms?
Zwei Links zum Zeichnen allgemein habe ich unter Hintergrundbild in Spiel? gepostet gehabt.
Um das (Neu-)Zeichnen per TrackBar zu ermöglichen, muß das Steuerelement einfach per
C#-Quelltext
neu gezeichnet werden (und im Paint-Ereignis reagierst du dann entsprechend der Eigenschaft TrackBar.Value).
PS: Eine automatische Animation würde per System.Windows.Forms.Timer-Komponente erfolgen, d.h. im Tick-Ereignis obige Methode aufrufen (dann entsprechend mit einer Animationsvariablen, z.B. currentWidth).
Edit: Die konkrete Form, also ein abgerundetes Rechteck, zeichnet man am besten per GraphicsPath.
Hier ein Artikel mit Code: Extended Graphics - An implementation of Rounded Rectangle in C# (such nach der Methode DrawRoundRectangle mit der aufgerufenen Methode GetRoundedRect).
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Sa 07.11.15 12:49
Ich habe hier schonmal einen Stern veränderlich gezeichnet: www.delphipraxis.net...star.html#post965130
Bei dem Stern hatte ich eine Umrechnung von Polar in Bildkoordinaten. Polarkoordinaten brauchst du eher nicht, aber eine solche Umrechnungsfunktion ist schon praktisch.
Die legt nämlich auch gleich den Koordinatenursprung in die Bildmitte und spiegelt die Y-Achse. Da wo ich InnerRadius.Value geschieben habe, kannst du natürlich auch Konstanten einsetzen, oder ein vielfaches der PictureBox Höhe oder Breite - dann würde die Form mit skalieren.
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: Sa 07.11.15 22:24
Hallo jfheins
danke für die Stern Beispiele die Beispiele schaue ich mir natürlich an und gucke was ich evtl davon verwenden kann.
Ich werde erstmal den weg von Th69 verwenden vielleicht hat sich dann auch das Thema erledigt.
Trotzdem danke!!
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: Sa 07.11.15 22:41
Hallo Th69,
mein Kenntnisstand mit Zeichnen in Forms ist = 0  .
Jedoch bin ich gestern abend schon so weit gekommen, ein Viereck mit dem Trackbar auch ein Rechteck zu stauchen.
Habe dazu Refresh() verwendet. Aber ich denke mit Invalidate() wird es auch funktionieren.
Danke für den Tipp.
Was meintest du mit der Animationsvariable currentWidth?
Ich mache das alle momentan folgendermaßen:
C#-Quelltext 1: 2: 3:
| Graphics x = this.CreateGraphics(); x.FillRectangle(Brushes.Red, xPos, yPos, xWidth, yHight); |
Wie finde ich den hier aus dem Rechteck die aktuelle Höhe und Breite?
Kannst du mir da ggf. eine Gedankenstütze geben?
Anderseits gehe ich daran die Methode DrawRoundRectangle zu verwenden da danke ich dir sehr für den Tipp
sieht so aus als wärs das was ich gesucht habe.
Viele Grüße
Moderiert von Th69: C#-Tags hinzugefügt
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: So 08.11.15 00:40
Hallo Th69,
ich habe mich jetzt an deinen Link versucht.
Wie beschrieben habe ich eine eigene Klasse in der Form erstellt.
Jedoch bekomme ich folgende Fehlermeldung, wenn ich ExtendedGraphics x = this.CreateGraphics(); anwende.
| Zitat: | | Fehler 2 Eine implizite Konvertierung vom Typ "System.Drawing.Graphics" in "System.Drawing.Extended.ExtendedGraphics" ist nicht möglich. C:\Users\User\documents\ .............. |
Kannst du mir da weiterhelfen?
Moderiert von Th69: C#-Tags hinzugefügt
Moderiert von Th69: Quote-Tags hinzugefügt
|
|
Th69
      

Beiträge: 4805
Erhaltene Danke: 1061
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: So 08.11.15 08:31
Hallo,
statt CreateGraphics solltest du im Paint-Ereignis auf e.Graphics zugreifen.
Und die Klasse hat nichts (direkt) mit der Graphics-Klasse zu tun, sondern du mußt diese nur im Paint-Ereignis benutzen, d.h.
C#-Quelltext 1: 2:
| ExtendedGraphics extendedGraphics = new ExtendedGraphics(e.Graphics); extendedGraphics.DrawRoundRectangle(...); |
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: So 08.11.15 12:27
| Zitat: | | Habe dazu Refresh() verwendet. Aber ich denke mit Invalidate() wird es auch funktionieren. |
Invalidate ist normalerweise zu bevorzugen. Refresh zeichnet im Gegensatz zu Invalidate sofort (Refresh ist die Kombination aus Invalidate und Update)
Bedeutet wenn du mehrere Controls auf der Form hast und änderst zum Beispiel durch eine Aktion mehrere gleichzeitig (z.B es reagieren alle auf ein resize der Form) werden alle geändert und alle zeichnen neu.
Bei Refresh : 1.Control resizen -> neuzeichnen -> 2.Control resizen -> neuzeichnen -> 3.Control resizen -> neuzeichnen etc.
Bei Invalidate : 1.Control resizen -> 2.Control resizen -> 3.Control resizen etc. -> neuzeichnen
Invalidate ist potentiell weniger aufwendig und weniger Flicker anfällig.
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: Mo 09.11.15 20:58
Hallo Th69,
ich danke dir für den Tipp bzw. den Denkanstoß  .
Ich melde mich sobald ich das geprüft habe.
Th69 hat folgendes geschrieben : | Hallo,
statt CreateGraphics solltest du im Paint-Ereignis auf e.Graphics zugreifen.
Und die Klasse hat nichts (direkt) mit der Graphics-Klasse zu tun, sondern du mußt diese nur im Paint-Ereignis benutzen, d.h.
C#-Quelltext 1: 2:
| ExtendedGraphics extendedGraphics = new ExtendedGraphics(e.Graphics); extendedGraphics.DrawRoundRectangle(...); | |
Allgemein wollte ich mal fragen wo wäre es einfacher zu Zeichen in WPF oder WinForms?
Viele Grüße
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: Mo 09.11.15 21:13
Hallo Ralf,
Ich habe leider das problem gehabt, wenn ich Invalidate in einem Ereignis angewendet habe und dahinter sofort neu geu´zeichnet habe, war das formular leer.
Bsp: Buttun Click: da habe ich zuerst Invalidate() durchgeführt und dahinter neu gezeichnet. Ohne Ergebnis.
Habe ich es durch Refresh() ersetzt, mit Erfolg gezeichnet. Erklärt aber das es eine Kombination ist wie du schon beschrieben hast.
Ich werde das erneut mit Invalidate() ausprobieren, weil ich gemerkt habe das auf einem Anderen Rechner diese Anwendung genau wie du beschrieben hast Flickert.
Ralf Jansen hat folgendes geschrieben : | | Zitat: | | Habe dazu Refresh() verwendet. Aber ich denke mit Invalidate() wird es auch funktionieren. |
Invalidate ist normalerweise zu bevorzugen. Refresh zeichnet im Gegensatz zu Invalidate sofort (Refresh ist die Kombination aus Invalidate und Update)
Bedeutet wenn du mehrere Controls auf der Form hast und änderst zum Beispiel durch eine Aktion mehrere gleichzeitig (z.B es reagieren alle auf ein resize der Form) werden alle geändert und alle zeichnen neu.
Bei Refresh : 1.Control resizen -> neuzeichnen -> 2.Control resizen -> neuzeichnen -> 3.Control resizen -> neuzeichnen etc.
Bei Invalidate : 1.Control resizen -> 2.Control resizen -> 3.Control resizen etc. -> neuzeichnen
Invalidate ist potentiell weniger aufwendig und weniger Flicker anfällig. |
Was ich vorhabe, ist ein Gegenstück mit einer gewissen Kraft zu stauchen. Arbeite gerade erstmal an den Grundformeln.
Dort wird es einige Parameter geben wie Geschwindigkeit, Kraft, Wärme usw. Aber zuerst muss ich mal hinbekommen das vernümftig zu Zeichen
Die Simulation für ein Werkstück ohne die oben genannten Parameter funktioniert jedoch fehlt mir noch der Tipp von Th69 für den Radius und dann gehts ins eingemachte  .
Viele Grüße
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 09.11.15 21:43
| Zitat: | | Bsp: Buttun Click: da habe ich zuerst Invalidate() durchgeführt und dahinter neu gezeichnet. Ohne Ergebnis. |
Du hast im Click Ereignis gezeichnet? Dann ist das das Problem. Jedes zeichnen musst du im Paint Ereignis ausführen.
Das was du im Click zeichnest ist nicht permanent. Jedes mal wenn neu gezeichnet werden muß wird der Paint Event ausgeführt. Zum Beispiel wenn du die Form minimierst/maximierst/resized und deshalb neugezeichnet werden müßte wird der Paint ausgeführt und natürlich nicht Click oder sonstwas. Es würde also nix gezeichnet werden und deine Controlfläche wäre leer. Oder anders ausgedrückt das was du irgendwo zeichnest wird sich nirgendwo gemerkt es reicht also nicht das einmal von irgendwo zu machen das zeichnen muß jedesmal erfolgen wenn ein neuzeichnen nötig ist und dazu gibt es den PaintEvent.
Du würdest also in Click irgendwas ändern zum Beispiel die Daten ändern die Einfluß auf das zeichnen haben udn Invalidate aufrufen. Invalidate wird dafür sorgen das kurzfristig mal Paint aufgerufen wird und dort muß dann das zeichnen erfolgen.
| Zitat: | | Allgemein wollte ich mal fragen wo wäre es einfacher zu Zeichen in WPF oder WinForms? |
WPF ist die aktuellere Technik und damit auf vieles besser vorbereitet. Wenn du also weder in WPF noch in Winforms Vorkenntnisse hast und sowieso eins davon erlernen musst nimm WPF. Ich würde aber nicht sagen das du das tun solltest weil es einfacher. Viele würden vermutlich sogar sagen das Winforms einfacher ist. Das hängt aber eher damit zusammen das, mit dem Modell wie Winforms funktioniert, viele schon Vorkenntnisse mitbringen und sich dort leichter tun, mich eingeschlossen. Wenn du aber nicht durch Vorkenntnisse belastet bist halt dich an WPF.
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: So 15.11.15 22:23
Hallo zusammen ich konnte eure letzten Tipps noch nicht ausprobieren.
Melde mich nur das dieses Thema weiterhin für mich interessant ist und noch nicht alles klar ist.
Bitte habt Geduld.
Bis demnächst, melde mich mit Ergebnissen
Viele Grüße
|
|
1mkRE
Hält's aus hier
Beiträge: 3
|
Verfasst: Sa 28.11.15 21:47
Hallo zusammen,
ich habe es jetzt hinbekommen ein abgerundetes Rechteck zu verformen.
Alles funktionierte super. Leider war es nicht meinen Anforderungen entsprechend.
So habe ich mich entschieden dieses Rechteck mit zwei Halbkreisen zu verbinden mittels Pie siehe Bild.
Die Animation sieht ganz gut aus jedoch stört mich hier an einigen stellen das Flackern der gezeichneten Bilder im Panel.
ich bekomme es einfach nicht hin auch mit den Gegenmaßnahmen z.B. hier [Artikel] Flackernde Controls und flackerndes Zeichnen vermeiden
helfen mir nicht weiter. Ich weiß halt nicht wo ich die DoubleBuffered Eigenschaft usw. einfügen soll.
Habe es im Panel Paint erreignis ausprobiert, leider sehe ich da keinen großen erfolg.
Folgendes wird gezeichnet:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| private void pPanel_Paint(object sender, PaintEventArgs e) { this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); this.DoubleBuffered = true;
e.Graphics.FillRectangle(Brushes.Black, xPosOben, yPosOben, 650, 20); e.Graphics.FillRectangle(Brushes.Black, xPosUnten, yPosUnten, 650, 20); e.Graphics.FillPie(Brushes.Green, LeftanglePosX, LeftanglePosY, LeftangleWidth, LeftangleHight, 90.0f, 180.0f); e.Graphics.FillPie(Brushes.Green, anglePosX, anglePosY, angleWidth, angleHight, -90.0f, 180.0f); e.Graphics.FillRectangle(Brushes.Green, xPos, yPos, xWidth, yHight); } |
Könnt ihr mir da weiterhelfen?
Vielen Dank.
Gruß
Moderiert von Th69: C#-Tags hinzugefügt
Moderiert von Th69: URL-Tag hinzugefügt
Einloggen, um Attachments anzusehen!
|
|
1mkRE
Hält's aus hier
Beiträge: 3
|
Verfasst: Sa 28.11.15 21:48
Siehe Bild:
Einloggen, um Attachments anzusehen!
|
|
Mathematiker
      
Beiträge: 2623
Erhaltene Danke: 1452
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 28.11.15 21:57
Hallo,
1mkRE hat folgendes geschrieben : | | Die Animation sieht ganz gut aus jedoch stört mich hier an einigen stellen das Flackern der gezeichneten Bilder im Panel. |
Obwohl ich von C# keine Ahnung habe, vermute ich, dass folgender Weg auch bei C# möglich ist:
1. Bitmap im Speicher erzeugen
2. Grafik im Bitmap zeichnen
3. Bitmap auf dein Element (Panel?) kopieren
4. Bitmap löschen
Beim Schnellgoogeln fand ich:
msdn.microsoft.com/d...287582(v=vs.71).aspx
Vielleicht hilft es ja etwas.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
1mkRE
Hält's aus hier
Beiträge: 3
|
Verfasst: Sa 28.11.15 22:09
Hi Mathematiker,
sieht verlockend aus dein Link.
So kompensiere ich mit Sicherheit das flackern.
Ich warte noch mögliche Antworten von Ralf Jansen oder Th69 ab vielleicht
haben die noch einige Tipps wie ich das Flackern im bei direkten Zeichnen aufs Panel verhindere bzw. vermeide.
Die Verformung des Rechtecks in dieses gerundete gepresste "Rechteck" arbeitet in einem Interval von 10ms.
Das flackern nervt total  .
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 28.11.15 22:17
Du solltest vom Panel ein eigenes Panel ableiten und in dessen Konstruktor dann die OptimzeDoubleBuffer Option setzen.
Beispiel hier.
|
|
Th69
      

Beiträge: 4805
Erhaltene Danke: 1061
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: So 29.11.15 11:43
Durch
C#-Quelltext 1:
| this.DoubleBuffered = true; |
wird nur die Form als DoubleBuffered markiert, nicht das enthaltene Panel.
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: So 29.11.15 23:33
Hallo Ralf danke für den Tipp ich kämpfe gerade damit wie ich das realisiere.
Das ableiten ist kein Problem aber wie realisiere ich das hab nie mit Steuerelementen vererbt brauchte ich bis dato nicht  .
|
|
mkRE 
      
Beiträge: 98
|
Verfasst: Di 01.12.15 22:38
Hallo zusammen,
ich brauche ggf. etwas denk Unterstützung.
ich habe jetzt eine Klasse wie folgt erstellt:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| public partial class UserControl1 : Panel { public UserControl1(): base() { this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
} } |
und zeichne jetzt wie folgt:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| private void UserControl1_paint(object sender, PaintEventArgs e) { e.Graphics.FillRectangle(Brushes.Black, xPosOben, yPosOben, 650, 20);
e.Graphics.FillRectangle(Brushes.Black, xPosUnten, yPosUnten, 650, 20); e.Graphics.FillPie(Brushes.Green, LeftanglePosX, LeftanglePosY, LeftangleWidth, LeftangleHight, 90.0f, 180.0f); e.Graphics.FillPie(Brushes.Green, anglePosX, anglePosY, angleWidth, angleHight, -90.0f, 180.0f);
e.Graphics.FillRectangle(Brushes.Green, xPos, yPos, xWidth, yHight);
lblStrokeValue.Text = angleHight.ToString(); } |
also wie vorher jedoch mit einem vererbten Steuerelement.
Trotzdem flackern zwei der elemente und zwar sind es auffälligerweise die letzten beiden objekte:
C#-Quelltext 1: 2:
| e.Graphics.FillPie(Brushes.Green, anglePosX, anglePosY, angleWidth, angleHight, -90.0f, 180.0f); e.Graphics.FillRectangle(Brushes.Green, xPos, yPos, xWidth, yHight); |
das Label mal außen vor gelassen. Das zeigt mir nur die Stauchhöhe als Zahl.
Habt Ihr eine Idee?
Viele Dank für die Tipps Ralf und TH69.
Moderiert von Th69: C#-Tags hinzugefügt
|
|
|