C# WindowsForms SetPixel

Djeurissen

Newbie
Registriert
Juni 2014
Beiträge
6
WindowsForms Bild wird nicht angezeigt

Tagchen, ich wollte eigentlich erstmal nur bei einer Bitmap alle Pixel in Rot ändern

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PictureCreator
{
    public partial class Creator : Form
    {
        Bitmap bitmap;
        Graphics graphics;
        string Path;

        public Creator(string FileName)
        {
            InitializeComponent();

            bitmap = new Bitmap(this.Width, this.Height);
            graphics = this.CreateGraphics();
            Path = FileName;
            Start();
        }

        private void Start()
        {
            graphics.DrawImage(bitmap, 0, 0);

            for (int X = 0; X < this.Width; X++)
            {
                for (int Y = 0; Y < this.Height; Y++)
                {
                    bitmap.SetPixel(X, Y, Color.Red);
                }
            }

            graphics.DrawImage(bitmap, 0, 0);
        }

    }
}

Allerdings wird bei mir nichts angezeigt wenn ich die bitmap zeichne...
Und bei Google finde ich die ganze Zeit nur erklärungen wie man SetPixel umgeht, da es zu langsam ist, aber zurzeit brauche ich das nicht...
 
Zuletzt bearbeitet:
Die Form wird 60 mal pro Sekunde neu gezeichnet (bzw. halt so wie die "Bildschirmaktualisierungsrate" eingestellt ist).
Das heißt sofort nachdem das Bild gezeichnet wurde, ist es auch schon wieder weg.

Das heißt du musst es jedes mal neu zeichnen, wozu es das "Paint" event gibt:

PHP:
public partial class Form1 : Form
    {
        private Graphics g;
        Bitmap bitmap = new Bitmap(500, 500);
        public Form1()
        {
            InitializeComponent();

            this.Paint += OnPaint;
            g = this.CreateGraphics();

            MakeBitmapRed();
        }

        private void OnPaint(object sender, PaintEventArgs paintEventArgs)
        {
            g.DrawImage(bitmap, new Point(0, 0));
        }

        private void MakeBitmapRed()
        {
            for (int x = 0; x < bitmap.Width; x++)
                for (int y = 0; y < bitmap.Height; y++)
                    bitmap.SetPixel(x, y, Color.Red);
        }
    }
 
Zuletzt bearbeitet:
Hi,
grundsätzlich solltest du sowas in dem Paint Event machen!

Greetz
hroessler
 
Vielen Dank für die Hilfe!

Noch eine Frage, wie kann ich dafür sorgen das meine Bitmap immer wieder geupdatet und gezeichnet wird.
Sprich ich will immer wieder einige Pixel bei meiner Bitmap ändern und die sollen dann wieder gezeichnet werden, zurzeit ist es bei mir so ich rufe meine Form PictureCreator von einer anderen Form auf, bei PictureCreator läuft dann einmal der ganze Code durch und dannach sbekomme ich es einfach nicht hin das er den Code nun immer wieder durchläuft ohne das sich mein Code aufhängt...
 
Zuletzt bearbeitet:
Es wäre hilfreich, wenn du den Code posten würdest.
Aber ich behaupte jetzt einfach mal, dass du den GUI-Thread (bspw. mit Schleifen) blockierst.
 
Das ich das ganze mit Schleifen blockiere ist mir auch klar^^

Code:
namespace PictureCreator
{
    public partial class Picture : Form
    {
        Bitmap p;
        Graphics g

        public Picture()
        {
            InitializeComponent();
            p = new Bitmap(this.Width, this.Height - GB_MenueStrip.Height);
            g = this.CreateGraphics();
        }

        private void B_StartCreator_Click(object sender, EventArgs e)
        {
            if (B_StartCreator.Text == "Start Creator")
            {
                if (FBD_SaveSpot.SelectedPath != "")
                {
                    if (Directory.Exists(FBD_SaveSpot.SelectedPath))
                    {
                        if (!File.Exists(FBD_SaveSpot.SelectedPath + "\\Picture_1.PNG"))
                            File.Create(FBD_SaveSpot.SelectedPath + "\\Picture_1.PNG");

                        B_StartCreator.Text = "Stop Creator";
                        this.Paint += OnPaint;
                    }
                    else
                    {
                        MessageBox.Show("Der Pfad\"" + FBD_SaveSpot.SelectedPath + "\" existiert nicht.");
                    }
                }
                else
                    MessageBox.Show("Sie haben kein Verzeichnis zum Speichern der Bilder ausgewählt.");
            }
            else
            {
                B_StartCreator.Text = "Start Creator";
            }
        }

        private void OnPaint(object sender, PaintEventArgs paintEventArgs)
        {
            
        }

    }
}

In meiner Funktion B_StartCreator_Click überschreibe? ich die OnPaint funktion(Falls man das so sagen kann, habe das noch nicht wirklich verstanden was das genau macht^^)
und von da an will ich nun in meiner OnPaint funktion immer wieder meine bitmap zeichnen lassen, Problem dabei OnPaint wird gar nicht erst aufgerufen. Ich habe es mal damit versucht OnPaint einfach selber aufzurufen und in OnPaint dann einfach immer Invalidate() auszuführen, aber ich bezweifle das dass eine saubere Lösung ist, zudem klappt diese eh nicht da meine Form trotz allem nie aktualisiert wird außer ich bewege das Fenster...
 
Mit "this.Paint += OnPaint" überschreibst du nichts, sondern du registrierst dich bei einem event (Ereignis).
Dieses event ruft dann jedes mal alle registrierten "Event Handler" auf, wenn die form sich neu zeichnet.

In der Regel macht man das nur ein einziges mal, wie oben in meinem Beispiel im Konstruktor (public Form1() {}).

In deinem Event Handler (private void OnPaint(...) {}) machst du dann das rein, was jedes mal ausgeführt werden soll (am saubersten ist es, wenn du hier nur das Zeichnen deiner Bitmap machst.

Für das regelmäßige ändern deiner Bitmap eignet sich ein Timer wenn die Änderung jeweils klein ist, oder eigener Threads wenn die Änderung viel Zeit benötig, dass sich deine GUI nicht aufhängt.

Invalidate() alleine bewirkt nicht, dass sich das Control neuzeichnet, das legt lediglich fest, dass es nicht mehr gültig ist.
Das Neuzeichnen wird dann erledigt, sobald im GUI Thread nichts mehr zu tun ist. Um eine sofortige Neuzeichnung zu erzwingen, musst du zusätzlich noch Update() aufrufen oder alternativ Invalidate() + Update() mit Refresh() ersetzen.

Du könntest aber auch ohne OnPaint() arbeiten, da Graphics auch ohne ein Neuzeichnen des Controls drüberzeichnen kann.

PHP:
public partial class BitmapDrawer : Form
    {
        private Graphics g;
        private Bitmap bitmap = new Bitmap(500, 500);
        private Timer timer = new Timer();
        private Random rand = new Random(34563546);

        public BitmapDrawer()
        {
            InitializeComponent();

            g = this.CreateGraphics();

            timer.Tick += DrawRandomBitmap;
            timer.Interval = 500;
            timer.Start();
        }

        private void DrawRandomBitmap(object sender, EventArgs e)
        {
            Color color = Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256));

            for (int x = 0; x < bitmap.Width; x++)
                for (int y = 0; y < bitmap.Height; y++)
                    bitmap.SetPixel(x, y, color);

            g.DrawImage(bitmap, new Point(0, 0));
        }
    }

So würde ich das ganze an deiner Stelle machen (mit dem Wissen das ich denke das du hast).
Wenn du das ausführst siehst du jedoch, dass das ganze sehr unperformant ist, was einerseits daran liegt, dass dort Bitmap.SetPixel verwendet wird und andererseits daran, dass kein Multi-Threading verwendet wird.

Da ich momentan eh nicht viel zu tun habe, kann ich dir anbieten, dass ich dir per Teamviewer helfe und Sachen beibringe.
Wenn du das willst, schreib mir einfach eine PN mit der ID und dem Passwort.


So, hoffe ich konnte dir helfen :)
 
Zurück
Oben