Probleme beim neuzeichnen von pictureBox

Schmatz001

Grünschnabel
Hallo zusammen,

mein Problem ist folgendes. Mein Programm bekommt über TCP alle paar Sekunden Informationen gesendet. Aus diesen Informationen lese ich den Pfad des Bitmaps aus, das in der pictureBox dargestellt werden soll (also muss immer, wenn das Prog Daten bekommt, das Image in der picBox aktualisiert werden)
Die Ausführung des Programms klappt auch, das einzige Problem das ich habe, ist die Aktualisierung. Die möchte er einfach nicht ausführen.


Code:
namespace WindowsApplication1
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        
        public void UpdateForm(string path)
        {

            if (pictureBox1.Image != null)
            {
                pictureBox1.Image.Dispose();
                pictureBox1.Image = null;
            }

            try
            {
                Bitmap bild_SSpiegel = new Bitmap(path);
                this.pictureBox1.Image = (Image)bild_SSpiegel;
                this.pictureBox1.Invalidate();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

Ich hoffe einer kann mir bei meinem Problem weiter helfen.

MfG
 
Statt Invalidate würde ich Refresh verwenden oder überhaupt ein Application.DoEvents. Abgesehen davon würde ich nicht über ein Bitmap gehen. Du kannst genauso gut
C#:
this.pictureBox1.Image = Image.FromFile(path);
verwenden, dann ersparst du dir den Cast.
 
Danke für deine schnelle Antwort,
habe mir deine Ratschläge zu Herzen genommen.

Code:
namespace WindowsApplication1
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        public void Update_picturebox(object path)
        {
            string strpath = Convert.ToString(path);

            if (pictureBox1.Image != null)
            {
                pictureBox1.Image.Dispose();
                pictureBox1.Image = null;
            }

            try
            {
                this.richTextBox1.AppendText(strpath);
                this.pictureBox1.Image = Image.FromFile(strpath);
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

Das Problem besteht aber leider immer noch. Ich erreiche einfach keine Aktualisierung der Komponenten. Ich habe in die Form noch ein richtextbox eingefügt, die mir den Pfad des Bildes anzeigen soll. Aber auch diese wird nicht aktualisiert. Egal ob ich nun Application.DoEvents() wie im oberen Beispiel oder .Refresh() verwende.

MfG
 
Ja die Methode wird aufgerufen und es wird keine Exception geworfen. Deshalb versteh ich nicht warum ich keine Aktualiesung erreiche.
 
Hmm .. erklär mal wie du die Methode abrufst, woher genau du den Pfad bekommst etc. Zumal ich den String auch nicht als Object übergeben würde, sondern gleich als String, aber das wird's wohl eher nicht sein.

Der Code sieht gut aus und müsste ansich funkionieren. Es könnte also eher an dem liegen, was rund um diese Methode noch so alles passiert.
 
Hier ist mal der Teil des Programms der aus einer Excel-Datei einen string ausliest und diesen string über die Methode LoadAll zerlegt.

Code:
class ExcelRead
    {
        //object vin ist der string der in der Excel-datei gesucht werden soll
        public void Read_Excel(object vin)
        {
            Load load = new Load();

            string path = "C:\\PVS.xls";
            string sheetName = "Tabelle1";
            string strSelect = @"SELECT * FROM [" + sheetName + "$]";

            string allvin = Convert.ToString(vin);
            string[] vinnr = new string[2];
            vinnr = Regex.Split(allvin, "\r\n");

            string vergleich;

            string[] allsub = new string[2];
           

            OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
                path + ";Extended Properties=\"Excel 8.0;HDR=NO;IMEX=1\";");

            DataSet ds = new DataSet();
            ds.CaseSensitive = false;
            
            try
            {
                conn.Open();

                OleDbCommand objCmd = new OleDbCommand(strSelect, conn);
                OleDbDataAdapter objAdapter = new OleDbDataAdapter();

                objAdapter.SelectCommand = objCmd;

                objAdapter.Fill(ds);

                DataTable tbl = ds.Tables[0];

                bool[] check = new bool[2];
                check[0] = true;
                check[1] = true;

                if (tbl.Rows.Count > 0)
                {
                    foreach (DataRow row in tbl.Rows)
                    { 
                        vergleich = Convert.ToString(row[0]);

                        for (int i = 0; i <= 1; i++)
                        {
                            if (vergleich == vinnr[i] && vinnr[i] != "no2vin")
                            {
                                allsub[i] = Convert.ToString(row[1]);

                                for (int k = 0; k <= anz; k++)
                                {
                                 /*
                                  * löschen aller Zeilen von anfang der Exceltabelle bis einschließlich der 
                                  * übereinstimmenden Vin-Nr.
                                  */
                                }

                                check[i] = false;
                            }

                            else if (vinnr[i] == "no2vin")
                            {
                                allsub[i] = vinnr[i];
                                check[i] = false;
                            }
                        }

                    }
                }

                for (int k = 0; k <= 1; k++)
                {
                    if (check[k] && (allsub[k] != "no2vin"))
                    {
                        allsub[k] = "not found";
                    }
                }
                
                conn.Close();

                if (allsub[1] == "no2vin")
                {
                    //Bei meinem Beispiel wird dieser Thread aufgerufen!!
                    Thread t_load = new Thread(new ParameterizedThreadStart(load.LoadAll));
                    t_load.IsBackground = true;
                    //allsub[0] enthält den Verweis auf den Pfad des Bildes welches später in der Methode
                    //update_picturebox geladen wird. 
                    t_load.Start(allsub[0]);   
                }

                else
                {
                    Thread t_loaddrei1 = new Thread(new ParameterizedThreadStart(load.LoadAllpb_Vorne));
                    t_loaddrei1.IsBackground = true;
                    t_loaddrei1.Start(allsub[0]);
                }     
            }

            catch (NullReferenceException ex)
            {
                MessageBox.Show(ex.Message);
            }

            catch (OleDbException ex)
            {
                MessageBox.Show(ex.Message);
            }

            catch (FieldAccessException ex)
            {
                MessageBox.Show(ex.Message);
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }

Code:
class Load
    {
        public void LoadAll(object allsub)
        {
            Form1 f = new Form1();
            LoadSchalter ls = new LoadSchalter();

            string sub = Convert.ToString(allsub);
            string[] subs = new string[17];

            if (sub == "not found")
            {
                for (int i = 0; i <= 16; i++)
                {
                    subs[i] = sub;
                }
            }
            else
            {
                subs = Regex.Split(sub, "\r\n");
            }

            //string_ssp ist der Pfad des Bildes welches in der Methode Update_picturebox in 
            //die pictureBox1 geladen werden soll.
            string path_ssp = ls.LoadSp(subs[0]);

            //Aufruf der Update_picturebox
            Thread t_update = new Thread(new ParameterizedThreadStart(f.Update_picturebox));
            t_update.IsBackground = true;
            t_update.Start(path_ssp);

        }
    }

Die Methode Upload_pictureBox steht ja oben.

MfG
 
Und da hast du dein Problem schon. Du rufst das Befüllen durch einen neuen Thread auf. Das funktioniert so aber nicht, da der neue Thread nicht auf den MainThread (unter dem laufen die Controls etc. einer Form) zugreifen kann und so auch nicht die PictureBox befüllen kann. Das wirst du über den Invoke() Handler des jeweiligen Controls lösen müssen.

Siehe dazu PictureBox.Invoke() und RichTextBox.Invoke(). In der MSDN gibt es dazu auch ein entsprechendes Beispiel.
 
Hmm hab die Methode Update_picturebox über .Invoke aufgerufen. Aber er aktualisiert die picbox immer noch nicht.

Hier ist mal der Code wie ich ihn jetzt habe
Code:
class Load
    {
        private delegate void d_updatepicbox(string path);

        public void LoadAll(object allsub)
        {
            Form1 f = new Form1();
            LoadSchalter ls = new LoadSchalter();

            string sub = Convert.ToString(allsub);
            string[] subs = new string[17];

            if (sub == "not found")
            {
                for (int i = 0; i <= 16; i++)
                {
                    subs[i] = sub;
                }
            }
            else
            {
                subs = Regex.Split(sub, "\r\n");
            }

            //string_ssp ist der Pfad des Bildes welches in der Methode Update_picturebox in 
            //die pictureBox1 geladen werden soll.
            string path_ssp = ls.Load_SSp(subs[0]);

            //Aufruf der Update_picturebox
            f.pictureBox1.Invoke(new d_updatepicbox(f.Update_picturebox), new object[]{path_ssp});
           
        }
}

Code:
public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        public void Update_picturebox(string path)
        {
            
            if (this.pictureBox1.Image != null)
            {
                this.pictureBox1.Image.Dispose();
                this.pictureBox1.Image = null;
            }

            try
            {
                MessageBox.Show(path);
                this.pictureBox1.Image = Image.FromFile(path);
                
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

Seltsam finde ich ja, dass doch normalerweise eine NotSupportedException geworfen werden müsste, wenn man in einem Thread auf ein Steuerelement zugreifen will, indem es nicht erstellt wurde.
 
Hab den Aufruf der Methode etwas geändert. Jetzt wird aber eine Exception geworfen (InvalidOperationException).

"Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde."

:(

Und zwar wird die Exception in dieser Zeile geworfen.
Code:
f.pictureBox1.Invoke(new d_updatepicbox(f.Update_picturebox), new object[] {f.pictureBox1, path})

die Methode selbst habe ich wie folgt geändert

Code:
public void Update_picturebox(PictureBox control, string path)
{
if (control.Image != null)
{
control.Image.Dispose();
control.Image = null;
}
try
{
MessageBox.Show(path);
control.Image = Image.FromFile(path);
//control.Refresh();
Application.DoEvents();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück