Windows Forms - picture box. How to delete an Imag

2019-08-15 14:11发布

问题:

I am working in an application where there is a conbobox and a picturebox. The user selects a path and the conbobox loads paths to 2000 images, and displays the first one. When the user changes the index of the conbobox the image displayed changes, but I don't know how to delete the image in the picturebox.

If I just overwrite the image it doesnt do the job, as when I do it repeatedly the program crashes because of memory. How do I delete a image Inside the picturebox?

EDIT: I made few changes and can't seem to reproduce the error again.. so maybe it was something else. but just for checking, is this code leaking memory?

tips: config is a singleton containing where some info, in this case, where the images are.

private: System::Void comboBox_image1_SelectedIndexChanged(System::Object^  sender, System::EventArgs^  e) {
         System::String^ aux;
         DIC_config* config=DIC_config::Instance();
         if(config->images_path!=NULL){
             aux=gcnew System::String(config->images_path);
             aux=aux+"\\CAM_0\\Snap_0_0"+(this->comboBox_image1->SelectedIndex+1)+".bmp";
             System::IO::FileStream^ image_file=gcnew System::IO::FileStream(aux,System::IO::FileMode::Open,System::IO::FileAccess::Read);
             System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(image_file);
             this->pictureBox_image1->Image=img;
             //img->~Bitmap(); this doesnt work, deletes the image of picturebox and makes the program chrash
        }

     }

回答1:

You have to dispose the old image. Forgetting to do so makes it likely your program runs out of unmanaged memory when the garbage collector doesn't run frequently enough. Bitmap objects are quite small, you can allocate thousands of them without ever triggering a GC, but can consume a lot of unmanaged memory for the pixel data. You dispose objects in C++/CLI with the delete operator, it calls IDisposable::Dispose().

Do note that the FileStream you use is also a disposable object. Doing it this way requires you to keep the stream opened while the bitmap is in use and close it afterwards. You correctly did not dispose the stream but forgot closing it. Too hard to get right, it is much easier to use the Bitmap constructor that accepts a string for the file path so the Bitmap class manages the underlying stream itself. Fix:

  aux = config->images_path;
  aux += ....;
  System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(aux);
  delete this->pictureBox_image1->Image;
  this->pictureBox_image1->Image = img;


回答2:

This doesn't work because you are trying to call destructor of the class, not the instance. Furthermore you do not need to call it as System::Drawing::Bitmap is under control of garbage collector, so the finalizer ( !Bitmap() ) will be called automatically if it's not referenced any longer.

What you can do if you want to close it in picturebox is

delete this->pictureBox_image1->Image;
image_file->Close(); //after closing/deleting the open bitmap

btw. your code is not pure c++, but c++/cli, so I've added the tag



回答3:

First set a null pointer to the Image property and refresh the pictureBox, as given below,

pictureBox_image1->Image = nullptr;
pictureBox_image1->Refresh();