none
请问如何删除pictureBox中的图片? RRS feed

  • 问题

  • 我的winform里面,左侧是listView用来显示小图列表,点击小图右侧pictureBox会显示相应的大图。listView和pictureBox的图片都是从项目里photo的文件夹中读取的。

    现在我想在listView中选择一张小图,然后按Delete键将photo文件夹中对应的图片删除,可是提示“正由另一进程使用,因此该进程无法访问该文件。”

    我知道现在这个winform正在访问这张图片所以无法删除,请问怎么可以先关闭它的访问再删除它,或是没有方法强行删除选中的张图片吗?

     


    • 已编辑 hkstb 2011年6月24日 6:40 完善一下问题
    2011年6月24日 6:37

答案

  • 你好

    你显示图片用

    this.pictureBox1.Load("IMG.JPG");

    删除的时候这样写

     pictureBox1.Image = null;
                if (File.Exists("IMG.JPG"))
                {
                    File.Delete("IMG.JPG");

                }

    试试~~

    希望有帮助。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 hkstb 2011年6月24日 10:07
    2011年6月24日 9:52
  • 你好

    其实这并不是唯一的方法。只要你Dispose掉Image也是可以delete的,

    定义:

    Image image = Image.FromFile("IMG.jpg");

    赋值:

    this.pictureBox1.Image = image;

    删除:

    this.pictureBox1.Image = null;
          image.Dispose();
          if (File.Exists("IMG.jpg"))
          {
            File.Delete("IMG.jpg");
          }
    

    原理就是你打开文件都会打开这个文件的handle,必须dispose这个对象,然后CLR内部发现这个dispose后,会调用windows Api CloseHandle关闭这个handle,然后才能删除文件。不然会抛出那个异常的。

    其实还有方法,就是image是来自流,而不是文件,就没有handle 的问题了。

    比如:

    Stream s = File.Open("IMG.jpg");
    Image temp = Image.FromStream(s);
    s.Close();
    pictureBox1.Image = temp
    

    删除:

    this.pictureBox1.Image = null;
          image.Dispose();
          if (File.Exists("IMG.jpg"))
          {
            File.Delete("IMG.jpg");
          }
    


    我上一个回复中的load方法,内部其实用了Image.FromStream,所以可以删除。

    所以要记住当打开一些本地的文件,数据库连接,网络socket,等等资源,都需要dispose掉。不然会出现类似的问题。

    希望对你有帮助。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 hkstb 2011年6月28日 4:14
    2011年6月25日 5:44
  • 你好

    我把你的代码几乎完整的运行在我的vs里,没什么问题呢。没有那个异常呢·~

     private Image temp = null;
        public Form1()
        {
          InitializeComponent();
          using (Stream s = File.Open("IMG.jpg", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
          {
            temp = Image.FromStream(s);
            s.Close();
            pictureBox1.Image = temp;
          }
    
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
          // if (e.KeyCode.ToString() == "Delete")
          // {
            string filepath = "IMG.jpg";
            pictureBox1.Image = null;
            temp.Dispose();
            if (File.Exists(filepath))
            {
              File.Delete(filepath);
            }
          // }
        }
    

    我就界面上一个picturebox和一个button,然后就是上面代码,没有那个异常。你可以建个项目试试。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 hkstb 2011年6月28日 4:14
    2011年6月25日 10:48

全部回复

  • 你好

    你显示图片用

    this.pictureBox1.Load("IMG.JPG");

    删除的时候这样写

     pictureBox1.Image = null;
                if (File.Exists("IMG.JPG"))
                {
                    File.Delete("IMG.JPG");

                }

    试试~~

    希望有帮助。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 hkstb 2011年6月24日 10:07
    2011年6月24日 9:52
  • 牛人啊!真的可以了!太感谢了!困扰我好些天了!不过这是为什么呢?我之前用pictureBox1.Image = Image.FromFile("IMG.JPG");就不行。为什么pictureBox1.Load("IMG.JPG");就可以呢?!!!!给讲一下好吗!
    2011年6月24日 10:07
  • 你好

    其实这并不是唯一的方法。只要你Dispose掉Image也是可以delete的,

    定义:

    Image image = Image.FromFile("IMG.jpg");

    赋值:

    this.pictureBox1.Image = image;

    删除:

    this.pictureBox1.Image = null;
          image.Dispose();
          if (File.Exists("IMG.jpg"))
          {
            File.Delete("IMG.jpg");
          }
    

    原理就是你打开文件都会打开这个文件的handle,必须dispose这个对象,然后CLR内部发现这个dispose后,会调用windows Api CloseHandle关闭这个handle,然后才能删除文件。不然会抛出那个异常的。

    其实还有方法,就是image是来自流,而不是文件,就没有handle 的问题了。

    比如:

    Stream s = File.Open("IMG.jpg");
    Image temp = Image.FromStream(s);
    s.Close();
    pictureBox1.Image = temp
    

    删除:

    this.pictureBox1.Image = null;
          image.Dispose();
          if (File.Exists("IMG.jpg"))
          {
            File.Delete("IMG.jpg");
          }
    


    我上一个回复中的load方法,内部其实用了Image.FromStream,所以可以删除。

    所以要记住当打开一些本地的文件,数据库连接,网络socket,等等资源,都需要dispose掉。不然会出现类似的问题。

    希望对你有帮助。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 hkstb 2011年6月28日 4:14
    2011年6月25日 5:44
  • Cookie Luo版主 你好

    之前的pictureBox1.Load方法确实管用,但是不稳定。只要程序关闭,再打开删除时就又成了“正由另一进程使用,因此该进程无法访问该文件”

    这两天网上找了找感觉还是用流可能会好一点。

    Stream s = File.Open("IMG.jpg", FileMode.Open);可是这第一步就出现“正由另一进程使用,因此该进程无法访问该文件”,图片连打也打不开,怎么回事呢?

    2011年6月25日 9:48
  • Stream s = File.Open("IMG.jpg", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)加上, FileAccess.Read, FileShare.ReadWrite可以读取图片了。
    但是删除时还是不行。
     
    private Image temp = null;
    
    private void listView1_Click(object sender, EventArgs e)
      {
    using (Stream s = File.Open("IMG.jpg", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
       {
        temp = Image.FromStream(s);
        s.Close();
        pictureBox1.Image = temp;
       }
    }
    
    
    private void listView1_KeyDown(object sender, KeyEventArgs e)
      {
    if(e.KeyCode.ToString()=="Delete")
    {
    string filepath = "IMG.jpg";
    
         pictureBox1.Image = null;
         temp.Dispose();
         if (File.Exists(filepath))
         {
          File.Delete(filepath);
         }
    }
     }
    


    File.Delete(filepath);是还是提示“正由另一进程使用,因此该进程无法访问该文件”

     

     

    • 已编辑 hkstb 2011年6月25日 10:19 说明
    2011年6月25日 10:16
  • 你好

    我把你的代码几乎完整的运行在我的vs里,没什么问题呢。没有那个异常呢·~

     private Image temp = null;
        public Form1()
        {
          InitializeComponent();
          using (Stream s = File.Open("IMG.jpg", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
          {
            temp = Image.FromStream(s);
            s.Close();
            pictureBox1.Image = temp;
          }
    
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
          // if (e.KeyCode.ToString() == "Delete")
          // {
            string filepath = "IMG.jpg";
            pictureBox1.Image = null;
            temp.Dispose();
            if (File.Exists(filepath))
            {
              File.Delete(filepath);
            }
          // }
        }
    

    我就界面上一个picturebox和一个button,然后就是上面代码,没有那个异常。你可以建个项目试试。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 hkstb 2011年6月28日 4:14
    2011年6月25日 10:48
  • 是不是还有别的地方也有在用这个图片的?
    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年6月25日 10:49
  • 还有listView用来显示小图列表。下面是listView显示代码


    private void ShowPhotoList()
            {
                DirectoryInfo di = new DirectoryInfo(sysPath + "Photo\\");
                int PtNum = di.GetFiles("*.jpg").Length;
                FileInfo[] f = di.GetFiles("*.jpg");

                ListViewItem[] lviArr = new ListViewItem[PtNum];
                for (int i = 0; i < PtNum; i++)
                {
                    lviArr[i] = new ListViewItem(f[i].ToString().Split(new Char[] { '.' })[0].ToString(), i);
                }
                listView1.Items.AddRange(lviArr);

                ImageList imageListLarge = new ImageList();
                imageListLarge.ImageSize = new Size(65, 50);
                for (int n = 0; n < PtNum; n++)
                {
                    imageListLarge.Images.Add(Bitmap.FromFile(sysPath + "Photo\\" + f[n].ToString()));
                }
                listView1.LargeImageList = imageListLarge;
            }

    • 已编辑 hkstb 2011年6月25日 11:22 说明
    2011年6月25日 11:17
  • 因为这句代码,所以还有别的地方没有dispose掉handle。

    imageListLarge.Images.Add(Bitmap.FromFile(sysPath + "Photo\\" + f[n].ToString()));

    所以你得在

    private void listView1_KeyDown(object sender, KeyEventArgs e)
     {
    if(e.KeyCode.ToString()=="Delete")
    {
    string filepath = "IMG.jpg";
    //这里加上逻辑,根据这个图片的的路径,在你的imageListLarge找到这个image把他从这个list里面删除,并且dispose掉了~~不然不删除还是会出现异常
       pictureBox1.Image = null;
       temp.Dispose();
       if (File.Exists(filepath))
       {
       File.Delete(filepath);
       }
    }
     }
    

     


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年6月25日 11:41
  • 确实是这里的问题

    imageListLarge.Images.Add(Bitmap.FromFile(sysPath + "Photo\\" + f[n].ToString()));

     

    现在我把它以流的形式给listView就好了,谢谢Cookie Luo版主的耐心教导。

    2011年6月28日 4:14
  • 呵呵,解决就好,感谢支持。
    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年6月28日 5:02