unendlich viele Graphics mit List<T> zeichen



  • Hallo allerseits.
    Ich bins wieder.
    Ich will mehrere Bälle(der selben Art) in einem Graphics BEfehl zeichnen. Dazu habe ich eine struct Ball gemacht und in dem eine Funktion(??kenne ich da nicht so gut aus) Namens DrawBall(in dem wird halt der Ball gezeichet).
    Ich will aber nun mehrere(bis unendlich) dieser Bälle zeichnen. Dazu habe ich eine List<Ball> gemacht, weiß aber nur nicht wie ich das nun im Paint Event umsetzten kann.
    Hier erstmal mein Code:
    [code

    ]using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace Punkte_zeichnen
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            struct Ball
            {         
                public int X;
                public int Y;            
    
                public void DrawBall(Graphics g)
                {              
                  g.FillEllipse(new SolidBrush(Color.Green), X, Y, 5, 5);
                }
            }
            private int i;
            Ball ball;
            private List<Ball> c = new List<Ball>();
    
            private void Form1_MouseClick(object sender, MouseEventArgs e)
            {
                Point Maus = PointToClient(MousePosition);
                ball.X = Maus.X;
                ball.Y = Maus.Y;
                i++;
                Refresh();          
            }
    
            private void Form1_Paint(object sender, PaintEventArgs e)
            {         
                ball.DrawBall(e.Graphics);            
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
            }
        }
    }
    

    Der Ball soll immer genau dort gezeichnet werden, wo man mit der Maus klickt. Im Moment bin ich soweit, dass ich den Ball genau dort zeichnen kann, aber halt immer nur einen.

    Wie kann ich das umsetzten?

    Ich habe es schon mit einer while Schleife probiert:

    [cs]while(Convert.ToInt32(c) > i)
    ball.DrawBall(e.Graphics)[/cs]
    

    aber da stürzte das Programm sofort ab(ohne Fehlermeldung des Compilers.

    Wie kann ich nun mehrere Bälle auf einmal zeichnen?
    ODer habe ich gar schon einen falschen Ansatz?

    mfg Mongole



  • Nee, nee der Ansatz ist schon so grob richtig. Was du machen musst, du musst einfach deine Liste mit Balls füllen und dann über die Liste iterieren und alle Bälle zeichnen lassen.



  • Wenn du aber mehrere Tausend Bälle zeichnen willst, dann wird der Refresh aber recht langsam werden (z.B. beim Minimieren und Wiederherstellen bzw. beim Bewegen des Fensters).
    Solange die Bälle sich nicht bewegen sollen, dann könntest du diese auch in eine Bitmap direkt zeichnen und diese dann einfach im Paint-Ereignis zeichnen.



  • Firefighter schrieb:

    Nee, nee der Ansatz ist schon so grob richtig. Was du machen musst, du musst einfach deine Liste mit Balls füllen und dann über die Liste iterieren und alle Bälle zeichnen lassen.

    Ja.
    Aber wie fülle ich nun eine Liste mit Balls? Kenne mich mit List<T> nicht so aus.

    Mein Denkansatz wäre einmal:
    Ich habe eine Liste mit balls Namens c. Ich habe ein int i das die Anzahl der Bälle bestimmt. Jedes Mal wenn die Taste geklickt wird soll sich die Anzahl der Bälle um 1 erweitern. Also i++.
    Aber weiter komme ich nicht. Theoretisch wird bei mir trotzdem immer der Ball ersetzt, da i erhöht wird und der Ball wieder unter i gespeichert wird.

    Was meisnt du mit iterieren?
    Und wie kann ich alle aus der list c zeichnen lassen.
    Mit if Abfragen müsste ich trotzdem so viele if abfragen machen wie es Bälle gibt und die Anzahl von denen soll sich ja erhöhen.

    Th69 schrieb:

    Wenn du aber mehrere Tausend Bälle zeichnen willst, dann wird der Refresh aber recht langsam werden (z.B. beim Minimieren und Wiederherstellen bzw. beim Bewegen des Fensters).
    Solange die Bälle sich nicht bewegen sollen, dann könntest du diese auch in eine Bitmap direkt zeichnen und diese dann einfach im Paint-Ereignis zeichnen.

    Das mit tausend wären dann nur Punkte ohne bewegung, aber wenn ich das ganze auf einer Bitmap speicher, kann ich keine Punkte rauslöschen. Deswegen mit einer List.

    Ich denke mein Hauptproblem ist die List mit Balls zu füllen und dann zu zeichnen(also eig das wichtigste)

    mfg Mongole



  • Wandernder Mongole schrieb:

    Aber wie fülle ich nun eine Liste mit Balls? Kenne mich mit List<T> nicht so aus.

    c.Add(new Ball());
    

    Wandernder Mongole schrieb:

    Was meisnt du mit iterieren?

    foreach(Ball ball in c) // Aussagekräftigerer Name für die Liste wäre auch toll
      ball.DrawBall(...);
    


  • Danke.

    Ich habe meinen Code nun entsprechend modifiezerit, aber nun hat sich ein weiteres Problem ergeben:Der wird der Ball dauernd an der Position (0,0) gezeichnte, also weiß ich nicht, ob es funktioniert, bzw. mehrere Bälle gezeichnet werden.

    Ich denke es liegt an dieser Stelle hier:

    [cs]private void Form1_MouseClick(object sender, MouseEventArgs e)
                {
                    [b]Point Maus = PointToClient(MousePosition);
                    ball.X = Maus.X;
                    ball.Y = Maus.Y;[/b]
                    Bälle.Add(new Ball());
                    Refresh();
                }[/cs]
    

    Aber es hat auch geklappt wie ich immer nur einen Ball zeichnen konnte. Muss ich da noch etwas beachten?

    Der Code ist immoment so:

    [cs]using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace Punkte_zeichnen
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            struct Ball
            {
                public int X;
                public int Y;
    
                public void DrawBall(Graphics g)
                {
                 g.FillEllipse(new SolidBrush(Color.Green), X, Y, 5,5);             
    
                }
            }
    
                Ball ball;
                private List<Ball> Bälle = new List<Ball>();
    
                private void Form1_MouseClick(object sender, MouseEventArgs e)
                {
                    Point Maus = PointToClient(MousePosition);
                    ball.X = Maus.X;
                    ball.Y = Maus.Y;
                    Bälle.Add(new Ball());
                    Refresh();
                }            
           }
    
                private void Form1_Paint(object sender, PaintEventArgs e)
                {
                    foreach (Ball ball in Bälle)
                        ball.DrawBall(e.Graphics);
    
                }
    
                private void Form1_Load(object sender, EventArgs e)
                {
    
                }
    
                private void timer1_Tick(object sender, EventArgs e)
                {
    
                }
            }
        }
    
    [/cs]
    

    Mongole



  • 1. Umlaute in Variablennamen sind GAAAANNZZZZ schlecht 😃
    2.

    private void Form1_MouseClick(object sender, MouseEventArgs e)
                {
                    Point Maus = PointToClient(MousePosition);
    Ball ball = new Ball();
    ball.X = Maus.X;
    ball.Y = Maus.Y;
                    Baelle.Add(ball);
                    Refresh();
    
                }
    

    du musst auch den Ball hinzufügen den du jedesmal beim klick erzeugst.



  • Mein Code sollte nur das Prinzip verdeutlichen, du solltest das nicht so 1:1 übernehmen. Du musst natürlich das Ball-Objekt, dass du mit den Koordinaten gefüttert hast der Liste hinzufügen und nicht noch eine Neues.
    Allerdings solltest du dir überlegen ob dein System so noch funktioniert wenn du mehrere Bälle hast, wenn du allen die Mauskoordinaten zuweist befinden sich alle an der gleichen Stelle und es ist effektiv wieder nur ein Ball zu sehen.

    PS: Nimm mal bitte die überflüssigen Whitespaces raus, das bläht deine Beiträge nur zusätzlich auf und macht sie unübersichtlich.



  • 1.Ich weiß aber es kürzt die Variable etwas ab und da mein Programm ja noch in der BetaPhase ist und deswegen noch nicht weltweit verbreitet werden kann, kann ich die Umlaute noch drinnen lassen^^(Ich weiß ich bin etwas größenwahnsinnig 😃 )
    2.
    Danke es hat geklappt. Du meinst wenn ich soviele Bälle habe, dass überall Bälle sind? Ja dann mach ich halt ein Limit oder eine Abfrage, ob diese Stelle schon nen Ball hat(wird schwierig^^)

    Ich habe da aber noch ein Frage:
    Ich möchte den Bällen jetzt auch Farben zuweisen(das immer wenn ein Timer tickt sich die Farbe ändert. Dazu Habe ich eine public Color clr in Ball. Dieser Farbe kann ich aber nur in DrawBall etwas zuweisen sonst wird der Ball nicht gezeichnet. Das sollte aber doch ganz einfach gehen. Halt so wie ich zB die X Koordinate geändert habe, aber: Fehlanzeige.
    Hier mal der relevante Codeausschnitt:

    [cs]struct Ball
            {
                public int X;
                public int Y;
                public Color clr;
    
                public void DrawBall(Graphics g)
                {
                    clr = Color.Red;
                    SolidBrush Pinsel = new SolidBrush(clr);
                    g.FillEllipse(Pinsel , X, Y, 5, 5);
                }
            }[/cs]
    

    Ich weiß, dass durch das clr = Color.Red; der Ball immer die Farbe rot bekommt, aber nur dann wird er gezeichnet. Gebe ich aber das ball.clr = Color.Red in einem Timer ein, dann wird es garnicht gezeichnet(Ja der timer ist enabled).
    Was kann man dagegen tun xD
    Wieso ist das alles so kompliziert:D

    mfg Mongole

    Whitespaces entfernt



  • Wandernder Mongole schrieb:

    Du meinst wenn ich soviele Bälle habe, dass überall Bälle sind?

    Ja, so wie du es jetzt geschrieben hast habe ich das gemeint. Die Abfrage ob da schon ein Ball ist könntest du dir sparen, wenn du nur die Position des Balles verändert, ich weiß allerdings nicht ob das das ist was du willst.

    Zum Thema Farbe:
    Veranlasst du in deinem Timer ein Neuzeichen (Invalidate)? Ansonsten weiß die Form ja nicht, dass sie die Bälle neuzeichnen soll.



  • Firefighter schrieb:

    1. Umlaute in Variablennamen sind GAAAANNZZZZ schlecht 😃

    Wieso? Es lebe Unicode/UTF! Man sollte sich allerdings an eine Sprache halten. Und da die Bibliotheken schon auf Englisch sind...

    Wenn ich aber korrektes Englisch haben will, muss auch der folgende Code funktionieren

    void NaïveAlgorithm() { }
    

    :p



  • Eventuell sollte sich der Threadersteller erstmal etwas mehr mit den eigentlichen Sprachefeatures beschäftigen eh er versucht etwas in Forms zu zeichnen, mag vielleicht für den Anfang leicht sein, aber es birgt ein paar feinheiten die man beachten sollte.
    Ich würd dir empfehlen mal zu googlen wie man zum beispiel mit List<T> umgeht und was generics usw sind.



  • hajb schrieb:

    Firefighter schrieb:

    1. Umlaute in Variablennamen sind GAAAANNZZZZ schlecht 😃

    Wieso? Es lebe Unicode/UTF! Man sollte sich allerdings an eine Sprache halten. Und da die Bibliotheken schon auf Englisch sind...

    Wenn ich aber korrektes Englisch haben will, muss auch der folgende Code funktionieren

    void NaïveAlgorithm() { }
    

    :p

    LOL sehr geil :p Dein Code finde ich dann bestimmt manchmal bei der dailyWTF :p kleiner Spass 😃



  • Danke für die Hilfe ich habe es jetzt geschafft.
    Zwar nicht die beste Lösung, aber es funktioniert:

    [cs]private void timer1_Tick(object sender, EventArgs e)
                {
                    if (MouseButtons == MouseButtons.Left)
                    {
                        Point Maus = PointToClient(MousePosition);
                        Ball ball = new Ball();
                        ball.X = Maus.X;
                        ball.Y = Maus.Y;
                        ball.clr = Color.Green;
                        Bälle.Add(ball);
                        Refresh();
                    }
                    if (MouseButtons == MouseButtons.Right)
                    {
                        Point Maus = PointToClient(MousePosition);
                        Ball ball = new Ball();
                        ball.X = Maus.X;
                        ball.Y = Maus.Y;
                        ball.clr = Color.Red;
                        Bälle.Add(ball);
                        Refresh();
                    }
    
                    Refresh();                
                }[/cs]
    

    Und ich werde mich jetzt weiter mit List<T> ausseinandersetzten(Scheint ja ziemlich nützlich zu sein 😃 )

    mfg Mongole



  • Auch wenn dein Projekt nicht so groß ist wie du in einem Post bereits gesagt hast, gewöhn es dir aber bitte nicht an Variablen mit Umlauten zu bestücken, es KANN gut gehen, aber vielleicht fällst du damit mal woanders auf die Nase, ist nur ein gutgemeinter Rat und mal ernsthaft, die zwei extra Buchstaben werden dich nicht umbringen, besonders nicht wenn dir Intellisense dabei hilft deine Variablen wiederzufinden :p


Anmelden zum Antworten