簡體   English   中英

Picturebox獲得大紅色X但我無法檢測或修復它

[英]Picturebox getting big red X but I can't detect or fix it

我目前正在與AForge合作,並有一個新的幀事件,將幀作為位圖發布到圖片框中。 它有90%的時間很棒......除非我在winform上搗亂。 更改組合框,移動窗口或任何類似的風險會導致Picturebox從視頻切換到大紅色X.下面的代碼示例:

    private void connectButton_Click(object sender, EventArgs e)
    {
        try
        {
            cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
            cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on
            cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
            cam.Start();
        }
        catch
        {
            MessageBox.Show("An error has occured with connecting to the specified webcam. The application will now close!");
            Application.Exit();
        }
    }

    private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
    {

        try
        {
            if (bitmap != null)
                bitmap.Dispose(); //Without this, memory goes nuts
            bitmap = new Bitmap(eventArgs.Frame);
        }
        catch { }

        //Draw some stuff on the images
        bitmap = AdjustBrightness(bitmap, brightnessMeter);
        bitmap = ApplyContrast(contrastMeter, bitmap);
        bitmap = Draw_Top_Line(bitmap);
        bitmap = Draw_Bottom_Line(bitmap);

        //Set the image into the picturebox
        this.Invoke((MethodInvoker)delegate
        {
            videoPictureBox1.Image = bitmap;
            frameRate++; //Keep track of the frame rate
        });

        GC.Collect(); //Without this, memory goes nuts

        this.Invoke((MethodInvoker)delegate {
            videoPictureBox1.Refresh(); //NOT NECESSARY. JUST TRYING TO FIX THE BIG RED X!
        });

        if (videoPictureBox1.Image == videoPictureBox1.ErrorImage)
        {
            cam.Stop(); //ALSO NOT NECESSARY> AGAIN, JUST TRYING TO FIX THE BIG RED X!
            cam.Start();
        }
    }

我在if(videoPictureBox1.Image == videoPictureBox1.ErrorImage)上放了一個中斷,即使大紅色X上升,它也會評估為false,因為圖像實際上是設置為位圖。 所以cam.Stop()和cam.Start()永遠不會運行(不確定這是否會有所幫助,但我想我會嘗試一下)。

videoPictureBox1.Refresh()每次都在運行,但是再次 - 它沒有什么區別。 還有大紅X.

正如我之前所說:如果我開始播放視頻並且什么都不觸摸,那么大紅色的X將永遠不會發生。 但是當我開始更改組合框或者拖動表單本身時,大紅色X的幾率呈指數上升。 有時我可以在它發生之前翻閱組合框10-12次,有時它會在第二次點擊組合框時發生。 : - \\

任何人都可以解釋這里發生的事情,也許可以提出一個關於修復它的最佳方法的建議嗎? 我還是很新的線程,所以我一直在努力解決這里發生的事情以及解決問題的最佳方法! 任何朝着正確方向的推動都將是一個巨大的幫助!

最后,我在調用Handle_New_Frame中包裝了所有內容。 它永久地完全消除了大紅色X問題。 > _>

private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
  this.Invoke((MethodInvoker)delegate
  {
    try
    {
        if (bitmap != null)
        {
            bitmap.Dispose(); //Without this, memory goes nuts
        }

        bitmap = new Bitmap(eventArgs.Frame);
    }
    catch { }

    //Draw some stuff on the images
    bitmap = AdjustBrightness(bitmap, brightnessMeter);
    bitmap = ApplyContrast(contrastMeter, bitmap);
    bitmap = Draw_Top_Line(bitmap);
    bitmap = Draw_Bottom_Line(bitmap);

    //Set the image into the picturebox
    this.Invoke((MethodInvoker)delegate
    {
        videoPictureBox1.Image = bitmap;
        frameRate++; //Keep track of the frame rate
    });

    GC.Collect(); //Without this, memory goes nuts
  });
}

肖恩哈格里夫斯(Shawn Hargreaves)對“厄運的大紅色X”進行了精彩而簡潔的寫作 我發現在處理WinForm組件突然顯示紅色“X”的一般情況下,它非常有用。

綜上所述:

  • 這是由控件從OnPaint事件中拋出異常引起的。
  • 一旦拋出,該控件將繼續顯示紅色X並跳過觸發OnPaint.
  • 要進行調試,請將調試器設置為捕獲公共語言運行時異常,然后執行通常所做的任何操作以獲取紅色X.調試器將在正確的位置停止,允許您進行調查並希望找到一種方法來阻止它。

嘗試在使用位圖的地方使用克隆。 例如

videoPictureBox1.Image = (Bitmap)bitmap.Clone();

總而言之,這是一個經過測試的最低限度,即使在調整大小,啟動,停止或改變分辨率時,也沒有顯示紅十字。

   public partial class PictureBoxVideo : Form
   {
      public PictureBoxVideo()
      {
         InitializeComponent();
         var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
         var videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
         videoSource.NewFrame += Handle_Very_New_Frame;
         videoSource.Start();
      }

      private void Handle_Very_New_Frame(object sender, NewFrameEventArgs eventArgs)
      {
         this.Invoke((MethodInvoker)delegate {
            pictureBox.Image = new Bitmap(eventArgs.Frame);
         });
      }
   }

請注意,我們稱之為videoSource.Start(); 來自GUI-(創建)-thread,但是從視頻(工作者)線程調用回調處理程序(Handle_Very_New_Frame)。

我認為這就是為什么我們需要兩個,Invoke和新的Bitmap,所以新的bmp也將從gui-thread生成。 但我只是在這里猜測,因為我無法提出證據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM