[C#] Problem mit Grafikobjekt

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Gibbon, 20. Dezember 2008 .

  1. 20. Dezember 2008
    Problem mit Grafikobjekt

    Hab ein Problem in C# mit dem Grafikobjekt, das ich im Event Form1_Paint bekomm. Beim Paint-Event wird der Funktion, die vom Paint-Event gefeuert wird, ein Parameter des Typs PaintEventArgs übergeben (e), in dem das Grafikobjekt für die Form drin is (e.Graphics). In diesem Event weise ich das Grafikobjekt der Variable g zu, damit ich es später in meiner Funktion DrawIt verwenden kann:

    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;
    using System.Threading;
    
    namespace Test
    {
     public partial class Form1 : Form
     {
     private Graphics g;
     
     public Form1()
     {
     InitializeComponent();
     }
    
     private void Form1_Paint(object sender, PaintEventArgs e)
     {
     g = e.Graphics; // Grafikobjekt zuweisen
     }
    
     private void DrawIt()
     {
     for (int i = 0; i < 255; i++) // Schleifen, die ein Farbmuster zeichnen, nix besonderes
     {
     for (int a = 0; a < 255; a++)
     {
     g.DrawRectangle(new Pen(Color.FromArgb(255, i, a, 255)), i, a, 1, 1); // Exception "Ungültiger Parameter"
     }
     }
     }
    
     private void button1_Click(object sender, EventArgs e)
     {
     DrawIt();
     }
     }
    }
    Es soll einfach ein simples Grafikmuster gezeichnet werden. Das Problem ist aber, dass bei g.DrawRectangle(...) eine Exception ("Ungültiger Parameter") auftritt (siehe Code). Wenn ich aber die zwei Schleifen fürs Zeichnen des Musters in Form1_Paint pack, kommt keine Exception und es funktioniert, also so:

    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;
    using System.Threading;
    
    namespace Test
    {
     public partial class Form1 : Form
     { 
     public Form1()
     {
     InitializeComponent();
     }
    
     private void Form1_Paint(object sender, PaintEventArgs e)
     {
     for (int i = 0; i < 255; i++)
     {
     for (int a = 0; a < 255; a++)
     {
     e.Graphics.DrawRectangle(new Pen(Color.FromArgb(255, i, a, 255)), i, a, 1, 1); // Exception "Ungültiger Parameter"
     }
     }
     }
     }
    }
    Wieso?
     
  2. 20. Dezember 2008
    AW: Problem mit Grafikobjekt

    Hab hier keine Entwicklungsumgebung, glaube aber das Problem gefunden zu haben.

    Code:
    private void Form1_Paint(object sender, PaintEventArgs e)
     {
     g = e.Graphics; // Grafikobjekt zuweisen
     [COLOR="Red"]//g wird hier in der Instanz von Form1_Paint erzeugt, ist damit private.[/COLOR]
     }
    
     private void DrawIt()
     {
     for (int i = 0; i < 255; i++) // Schleifen, die ein Farbmuster zeichnen, nix besonderes
     {
     for (int a = 0; a < 255; a++)
     {
     [COLOR="Red"]//g ist hier nicht verfügbar, da die Instanz hier nicht mehr existiert.[/COLOR]
     g.DrawRectangle(new Pen(Color.FromArgb(255, i, a, 255)), i, a, 1, 1); // Exception "Ungültiger Parameter"
     }
     }
     }

    Workaround:
    Code:
     private void DrawIt([COLOR="Lime"]EventArgs e[/COLOR])
     {
     [COLOR="Lime"] g = e.Graphics;[/COLOR]
     for (int i = 0; i < 255; i++) // Schleifen, die ein Farbmuster zeichnen, nix besonderes
     {
     for (int a = 0; a < 255; a++)
     {
     g.DrawRectangle(new Pen(Color.FromArgb(255, i, a, 255)), i, a, 1, 1); // Exception "Ungültiger Parameter"
     }
     }
     }
    
     private void button1_Click(object sender, EventArgs e)
     {
     DrawIt([COLOR="Lime"]e[/COLOR]);
     }
    
    Edit: Workaround wird sehr wahrscheinlich nicht funktionieren, das Problem sollte aber trotzdem klar sein oder?
    Bei DrawIt musst du anstatt dem EventArgs die Form übergeben!
    Schäze mal, dass das für dich kein Problem darstellen sollte.
     
  3. 20. Dezember 2008
    AW: Problem mit Grafikobjekt

    Es liegt nicht daran, dass das Graphics-Objekt nicht mehr existiert - denn es existiert immer noch.

    Doch dem Graphics-Objekt fehlt die Zeichenfläche. Wenn du ein PaintEventArgs-Objekt erstellst, dann musst du immer ein Rectangle noch mit angeben, welches die Basis für die Zeichenoperation darstellt.
    Und diese "Basis" hast du "dann" nicht mehr.



    edit:

    Auch um die Geschwindigkeit zu erhöhen, kannst du deinen Zeichenvorgang über eine Picturebox laufen lassen. Des Weiteren wird dann auch ein "flackern" des Formulares nicht mehr auftreten.
    Du benötigst auf dem Formular eigentlich nur eine Picturebox, und folgenden Code:

    Code:
     Graphics graphic;
     Bitmap _bitm;
     
     [COLOR="Sienna"]private void drawIt()
     {[/COLOR]
    
     _bitm = new Bitmap(
     Width,
     Height,
     PixelFormat.Format24bppRgb);
    
     [COLOR="Green"]// Der Picturebox das Bild zuweisen[/COLOR]
     pictureBox1.Image = _bitm;
    
     [COLOR="Green"]// Das Graphics-Objekt holen[/COLOR]
     graphic = Graphics.FromImage(pictureBox1.Image);
    
    
     [COLOR="Green"]// Deine Sachen in die Picturebox schreiben.
     // Die Picturebox kümmert sich im Anschluss immer selbst darum,
     // dass ihre "Daten" korrekt gezeichnet bleiben.[/COLOR]
     for (int i = 1; i < 255; i++)
     {
     for (int a = 1; a < 255; a++)
     {
     graphic.DrawRectangle(
     new Pen(Color.FromArgb(255, i, a, 255)),
     new Rectangle(i, a, 1, 1));
     }
     }
    
     [COLOR="Sienna"]}[/COLOR]
    
     
  4. 21. Dezember 2008
    AW: Problem mit Grafikobjekt

    Die Lösung von Tanya funktioniert, trotzdem auch erstmal danke an styxx. Hab aber noch ne Frage: wenn ich drawIt aufruf, dauert es ein bis zwei Sekunden, dann taucht die Form mit Picturebox auf, in dem das Muster gezeichnet ist. Ich will aber zusehen, wie es gezeichnet wird. Also dachte ich mir, ich versuch es mal mit Application.DoEvents() und/oder pictureBox1.Update() in der zweiten Schleife. Bringt aber nichts, hinterher ist sogar die ganze Picturebox schwarz, ohne mein Muster.

    Außerdem hab ich einen Timer gemacht, der mit ein Viereck an einer bestimmten Position zeichnet, die sich nach jedem Timer-Durchlauf um 1 erhöht (die Linie soll also von links nach rechts "wandern". Hier hab ich wieder das Problem, dass ich beim Zeichnen der Linie nicht zuschauen kann. Ich muss die Form immer erst aus dem Bildschirm rausziehen oder mit einem anderen Fenster verdecken, damit die Linie größer wird. Außerdem geht das recht langsam, obwohl ich das Timer-Intervall auf 1 gestellt hab.

    Hier der Code für die Linie:

    Code:
    private int iX = 0;
    
    private void timer1_Tick(object sender, EventArgs e)
    {
     graphic.DrawRectangle(
     new Pen(Color.Red),
     new Rectangle(iX, 1, 1, 1));
    
     Application.DoEvents();
     pictureBox1.Update();
    
     iX++;
    }
    Der Code für die Grafikobjekte:

    Code:
    private void Form1_Load(object sender, EventArgs e)
    {
     _bitm = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
     // Der Picturebox das Bild zuweisen
     pictureBox1.Image = _bitm;
    
     // Das Graphics-Objekt holen
     graphic = Graphics.FromImage(pictureBox1.Image);
    }
    Wie gesagt bekomm ich ohne DoEvents und Update das gleiche Ergebnis.
     
  5. 21. Dezember 2008
    AW: Problem mit Grafikobjekt

    probiers mit einem einfachen
    Code:
    System.Threading.Thread.Sleep(200);
    an der Stelle wo du warten willst. Das Programm geht dann erst weiter, wenn die Zeit (in dem Fall 200 Millisekunden) abgelaufen ist.
     
  6. 21. Dezember 2008
    AW: Problem mit Grafikobjekt

    Mit pictureBox1.Refresh() statt .Update() funktioniert es. Danke dafür an n0TaX, der mir eine PN geschrieben hat. Leider zeichnen sich die einzelnen Linien aber sehr sehr langsam im Vergleich dazu, wenn ichs ohne Refresh() mach (dann taucht aber wie gesagt das Muster erst auf, wenn es komplett gezeichnet ist und ich kann nicht beim Zeichnen zuschauen). Vielleicht sollte ich doch auf DirectX umsteigen

    Das einzige, was neu dazugekommen ist, hab ich rot markiert:

    Code:
    for (int i = 1; i < 255; i++)
    {
     for (int a = 1; a < 255; a++)
     {
     graphic.DrawRectangle(
     new Pen(Color.FromArgb(255, i, a, 255)),
     new Rectangle(i, a, 1, 1));
    
     [COLOR="Red"]pictureBox1.Refresh();[/COLOR] // ohne das dauert es nur 1-2 Sekunden
     }
    }

    Hat leider nix gebracht.
     
  7. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.