【问题标题】:C# - Updating pictureBox.Image during Runtime causes ErrorC# - 在运行时更新 pictureBox.Image 会导致错误
【发布时间】:2017-06-20 06:06:41
【问题描述】:

我正在尝试在运行时更改 pictureBox.Image。我有几个存储图片的模型类,每当我单击 MenuStripItem 时,我都会调用方法“ChangePictureBoxImages”。直到那时没有错误(pB 是不可见的!)但是一旦我调用该方法使 pB 可见,我就会得到一个错误。错误代码:“System.Drawing.dll 中发生了“System.ArgumentException”类型的未处理异常。

研究表明我应该处理图片框并将其设置为“null”,但这没有帮助。

我的代码:

using (Image current = BitmapManipulator.EvaluateMesurement(CSV_Name1, max_Rows, max_Col, var.TopImage, var.BitmapToManipulate, pB_ColourScale_Evaluation.Image, var.BitmapToManipulate, var.Filepath, var.FoldID))
                {

                    var.LastEvaluationImage = current;
                    BitmapManipulator.CombineImagesAndSaveThem_Evaluation(var.TopImage, var.BitmapToManipulate, pB_ColourScale_Evaluation.Image, var.Filepath, var.FoldID);  //saves the Files as jpg 
                    if (var.CurrentlyShownToUser) //checks if the MenuStripItem is the active one
                    {
                        if (var.LastEvaluationImage == null) { MessageBox.Show("the image is null");} //only for debugging purpose -> does never call
                        ChangePictureBoxImages(); 

                    }
                }

还有 ChangePictureBoxImages():

      public void ChangePictureBoxImages()
    {

        foreach (Fold fold in FoldExisting)    
        {
            if (fold.FoldID == LastSelectedMenuStripItem_Name)       //the clicked item is the last Selected MenuStripItem
            {
                if (fold.LastEvaluationImage != null)
                {
                    Debug.WriteLine(pB_Evaluation_Bottom.Image.ToString() + "   " + fold.LastEvaluationImage.ToString());
                    pB_Evaluation_Bottom.Image = fold.LastEvaluationImage;
                }


                pB_Evaluation_Top.Image = fold.TopImage;
            }

        }
    }

在此之前没有错误,一旦我调用“pB_Evaluation_Bottom.visible = true”,错误就会出现。 (或者如果我首先调用可见方法,则在更改图像时会出现错误!)在 MenuStripItem 上单击 2 次时也会出现错误。我从 Class Fold 加载图片如下:

这将在折叠类中设置一个图像,然后该图像将被操作并存储在 LastEvaluationImage 中

        private void setTheImages(string PictureToManipulate, string PathToTopImage)
    {
        try
        {
            this.BitmapToManipulate_intern = (Image)Image.FromFile(@PictureToManipulate, true);
            this.TopImage_intern = (Image)Image.FromFile(@PathToTopImage, true);
        }
        catch (ArgumentNullException ex)
        {
            Debug.WriteLine("The BitMap for the manipulation process and the top image is not created.");
        }

    }

以及最后一张图片存储的 LastEvaluationImage -> 这将被称为新的 pb.Image

        private Image LastEvaluationImage_intern;
    public Image LastEvaluationImage
    {
        get
        {
            return this.LastEvaluationImage_intern;
        }
        set
        {
            if (LastEvaluationImage_intern != null) { LastEvaluationImage_intern.Dispose(); LastEvaluationImage_intern = null; }
            this.LastEvaluationImage_intern = value;
            this.LastEvaluationTime_intern = DateTime.Now;
        }
    }

我知道这有点复杂,但我希望有人能帮助我。

提前致谢!

更新:错误必须在以下代码中: BitmapManipulator.EvaluateMeasurement 代码:

 public Image EvaluateMesurement(double[][] MeasuredValues, int max_Rows, int max_Col, Image pB_Evaluation_Top, Image pB_Evaluation_Bottom, Image pB_EvaluationColourScale, Image ManipulatedBitmap, string PathMeasurementFiles, string Foldname) 
    {

        using (Bitmap bitmap = new Bitmap(ManipulatedBitmap))  
        {
            // the data array sizes:
            int number_nio = 0;
            int number_total = 0;
            List<FileInfo> LastFiles;   
            int got_number_for_trends = Properties.Settings.Default.TrendNumber;



            SolidBrush myBrush = new SolidBrush(red);

            using (Graphics g = Graphics.FromImage(bitmap))
            {
                Random rnd = new Random(8);
                int[,] data = new int[max_Col, max_Rows];



                // scale the tile size:
                float sx = 1f * bitmap.Width / data.GetLength(0);
                float sy = 1f * bitmap.Height / data.GetLength(1);

                LastFiles = FM.GetLastFiles_Trend(ref got_number_for_trends, PathMeasurementFiles);  
                double[][] CSV_Statistiken = FM.LastFilesToCSV(got_number_for_trends, true, LastFiles, PathMeasurementFiles);    


                for (int x = 0; x < max_Col; x++)     
                {
                    for (int y = max_Rows - 1; y >= 0; y--)  
                    {
                        number_total++;
                        RectangleF r = new RectangleF(x * sx, y * sy, sx, sy);

                        if (MeasuredValues[y][x] < Properties.Settings.Default.Threshhold) 
                        {
                            number_nio++;
                            if (CSV_Statistiken[y][x] == Properties.Settings.Default.TrendNumber)  
                            {
                                myBrush.Color = Color.FromArgb(150, black);
                                g.FillRectangle(myBrush, r);
                            }
                            else
                            {
                                myBrush.Color = Color.FromArgb(150, red);
                                g.FillRectangle(myBrush, r);
                            }

                        }
                        else    
                        {

                            myBrush.Color = Color.FromArgb(150, green);
                            g.FillRectangle(myBrush, r);
                        }

                    }


                }
            }

            return bitmap;  
        }
    }

这个返回的位图将存储在 fold.LastEvaluationImage 中,如下所示:

using (Image current = BitmapManipulator.EvaluateMesurement(CSV_Name1, max_Rows, max_Col, var.TopImage, var.BitmapToManipulate, pB_ColourScale_Evaluation.Image, var.BitmapToManipulate, var.Filepath, var.FoldID))
            {

                var.LastEvaluationImage = current;
            }

【问题讨论】:

  • fold.LastEvaluationImage 的类型是什么?
  • 它是一张图片 (jpeg)
  • .Net 数据类型Image?你是从文件还是资源中加载它?
  • 我将它加载到“LastEvaluationImage”中,代码​​在问题中,最后一部分,它在 1 中被修改。我发布的代码,然后保存在“当前”中,然后存储在最后fold.LastEvaluationImage.( with set this.LastEvaluationImage_intern = value;) 中的代码是您的意思吗?或者你想要别的东西?感谢您的宝贵时间
  • 您是否尝试将 jpeg 文件直接设置为 PictureBox 的源?仅用于调试目的。可能是文件有问题

标签: c# image picturebox


【解决方案1】:

您正在返回已处理的位图。你不能画出不再存在的东西也就不足为奇了:)

using (bitmap) 在这种情况下是您最不想要的。 bitmap 必须在使用范围内存活的时间更长。调用者中的using (current) 也有同样的问题——你再次过早地处理图像。只有在很明显它不会再被使用时,你才能处置它——例如。当您将其替换为新图像时。

详细地说,using 在您离开其作用域时只调用Dispose。对于Bitmap(它只是一个围绕 GDI 位图的“薄”包装器),这会释放存储实际图像数据的内存。没有任何有趣的东西,所以没有什么可画的(就 GDI 而言,你基本上会调用DrawBitmap(NULL))。

【讨论】:

  • 嗯我明白你的意思,但是当我使用时: using (Bitmap b = new Bitmap(ManipulatedBitmap) { ..... some functions return b; } 不应该首先返回位图 b 并且之后处理?还是返回的位图也会在之后处理?基本上 dispose 也会删除所有引用,如“return b”?还是只是位图本身?
  • @christian890 “被处置”不是引用的属性,而是对象的属性。当您返回位图时,您并没有复制 - 您只是返回对原始位图的引用。您正在销毁一个对象 - 无论有多少对被销毁对象的引用,它仍然被销毁。
  • 啊该死的!那可能真的是这样!生病检查并回答结果!谢谢,这确实有帮助,几天来一直在寻找这个!愚蠢的我!
  • @christian890 请注意,在 .NET 中,“disposed”和“destroyed”实际上是正交的——你永远不会真正“销毁”任何对象,GC 会这样做。按照设计,Dispose 用于释放垃圾收集器不跟踪的 非托管(非 .NET)资源。无法从您的代码中确定性地销毁 .NET 对象。如果您来自 C++ 之类的背景,这些事情可能会让人感到困惑,因为它们似乎 类似于某些 C++ 概念,但很少如此。确保以全新的眼光看待事物,尤其是在内存管理方面 - .NET 非常不同。
  • 这完全解决了我的问题!太感谢了!我很乐意听取您的建议!我认为这正是我的问题,我真的是 - .Net 的新手,并且来自 C++ =) 祝你有美好的一天!谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
相关资源
最近更新 更多