在使用图片框性能问题(Performance issue while using PictureBo

2019-10-19 09:15发布

我工作的一个应用程序在Visual Studio 2010中,我在C ++ / CLI编码。
在我以前的问题,我不得不从一个串口数据系列问题。 现在,它似乎确定,现在我想要绘制他们。
我不想用Chart ,所以我想用使用该类手工功能Graphics 。 为了测试我的代码,我创建了两个数组:第一个是充满了来自高斯未来值。 第二个充满了随机数。
当我绘制的价值观,我想看看我的情节成长和更新,就像一个示波器。 第二Do_Plot管理,以“删除点”的背景色绘制它们。 所有的代码按预期工作,但我遇到的问题与表演。 如果我跑在我的电脑代码,我的系列每500/700毫秒绘制。
有时,它会减慢到1500毫秒,然后回来得更快。
我试图运行在我同事的电脑代码,我注意到系列绘制在第一个每170ms,而该系列绘制在第二个每950ms。 这是代码:

System::Void Form1::button1_Click(System::Object^  sender, System::EventArgs^  e) {
    button1->Enabled = false;

    array<float,1>^ Gauss = gcnew array<float,1>(1001);

    array<float,1>^ Rumore = gcnew array<float,1>(1001);


     /*Some useful variables*/
     Random^ generatore = gcnew Random;
     float a = safe_cast<float>(Math::Round(5/(SIGMA*Math::Sqrt(2*PI)), 2));
     float b = safe_cast<float>(2*(SIGMA*SIGMA));

      /*Start */


      float portante; 
      float r;
      float s;

      int convX =1000/1000;
      int convY =500/2;  

      /*time variables */  

      int bias = 50;
      int dif =600;  

      /*Gap between drawing and removing*/  

      int k = 3; 
      int e1 = 0;


     for ( ; ; ) {

          /*Start*/
          clock_t Start = clock();

          if(textBox1->Text==""){
            portn = 5;
          }
          else
            portn = float::Parse(textBox1->Text);

          /*temp variables to go out the for cycle */
          portante = portn;
          r = rand;
          s = sig;

          /ckeck state is OK */
          check = 0;


            for(int i = 1; i<=1000; i++) {

                Gauss[i] = safe_cast<float>(Math::Round( a*s*Math::Exp(-Math::Pow(((0.01*1*(i))-portante), 2)/b), 2));

                Rumore[i] = safe_cast<float>(Math::Round(r*generatore->NextDouble(), 2));
                bool clipSup = ClipSup(2, Gauss[i]+Rumore[i]);

                if(clipSup==true) {
                    Gauss[i] = 1.99f;
                    Rumore[i] = 0;
                }
                Do_Plot(g, disegna, i-1, Gauss[i-1]+Rumore[i-1], i, Gauss[i]+Rumore[i], convX, convY);


                e1 =(k+i)%1000;
                Do_Plot(g, rimuovi, e1, Gauss[e1]+Rumore[e1], e1+1, Gauss[e1+1]+Rumore[e1+1], convX, convY);




                /*Ckeck if go out for cycle*/
                if(check == CODE_1 ) {
                    portante = portn;
                    break;
                }
                if(check == CODE_2 ) {
                    r = rand;
                    break;
                }
                if(check == CODE_3 ) {
                    s = sig;
                    break;
                }

            }

             clock_t Stop = clock();
             int Diff = Stop-Start;
             label8->Text = Convert::ToString(Diff);
             int tempDiff = (Stop-Start)+bias;
             if(tempDiff>dif)
             {

                //Do_Axes(g);           /*Do Axes*/
                //Do_Grid(g);           /*Do Grid */
                Application::DoEvents();
                dif = 600;
                bias = 0;
            }
            else
                bias +=50; //Else bias grows
      }


}

其中Do_Plot是:

void Do_Plot(Graphics^ g, Pen^ penna, int Xi, float Yi, int Xf, float Yf, int convX, int convY) {


    g->DrawLine(penna, (convX*Xi+50), safe_cast<int>(500-(Yi*convY)+50), 
        (convX*Xf+50), safe_cast<int>(500-(Yf*convY)+50)); 
}

我宣布Graphics^ g这里:

public ref class Form1 : public System::Windows::Forms::Form
{
Graphics^ g; 
public:
    Form1(void) 
    {
        InitializeComponent();
        //
        //TODO: aggiungere qui il codice del costruttore.
        //
        g = pictureBox1->CreateGraphics();

    }

Onestly我不知道为什么我的代码工作如此不同,当它运行在另一台电脑。 我认为这个问题是g = pictureBox1->CreateGraphics(); 但我只是做了一些假设。 任何形式的帮助将非常感激,因为我卡在这一块,因为前一周!
非常感谢!
埃米利亚诺

Answer 1:

我要给你用C / C代码++。 然后将找到如何做到这一点在C ++ / CLI

首先初始化(begining button_click),我们将使用对象:

RECT rt = {0, 0, 1200, 600};
HBITMAP hBitmap = NULL;
HPEN hLinePen = NULL;
HDC hdcPctrBox = NULL, hdc = NULL, hdcMemTempImage = NULL;
HBRUSH hBrush = NULL;
POINT arrayPnt[1000]; //array of points

hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
hdcMemTempImage = CreateCompatibleDC(hdc);

hBitmap = CreateCompatibleBitmap(hdc, 1200, 600);  
SelectObject(hdcMemTempImage, hBitmap);  

hLinePen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); //width of pen = 1,and color (255, 0, 0)
SelectObject(hdcMemTempImage, hLinePen);

hBrush = CreateSolidBrush(RGB(100, 100, 255)); //color of picturebox

然后:

for ( ; ; ) {
    /*Start*/
    clock_t Start = clock();

    FillRect(hdcMemTempImage, &rt, hBrush); //clear the hdcMemTempImage with the picturebox color
    //your code continues...

for(int i = 1; i<=1000; i++)一次添加一个点:

arrayPnt[i - 1].x = X; //calculate X
arrayPnt[i - 1].x = Y; ////calculate Y

而finaly我们绘制,后for循环和clock_t表示停止之前(我们不需要的Do_Plot()):

Polyline(hdcMemTempImage, &arrayPnt, 1000);
BitBlt(hdcPctrBox, 0, 0, 1200, 600, hdcMemTempImage, 0, 0, SRCCOPY);

clock_t Stop = clock();
//your code continues...

编辑:使用原始密码( 你不需要 RT,HBITMAP,HBRUSH,hdcMemTempImage,arrayPnt和HDC)和而不是调用Do_Plot()添加以下代码:

//create two pens, one with the color you want hLinePen, and another with the color of picturebox hLinePenErase
//inside for(int i = 1; i<=1000; i++)
(some code...)
if(clipSup==true) {
    Gauss[i] = 1.99f;
    Rumore[i] = 0;
}

SelectObject(hdcPctrBox, hLinePen); //the pen to draw the line
MoveToEx(hdcPctrBox, xStart, yStart, NULL); //start point of line
LineTo(hdcPctrBox, xEnd, yEnd); //end point of line

SelectObject(hdcPctrBox, hLinePenErase); //the pen to erase the line
MoveToEx(hdcPctrBox, xStartErase, yStartErase, NULL); //start point of line to erase
LineTo(hdcPctrBox, xEndErase, yEndErase); //end point of line to erase
(code continues...)

要删除您的资源:

HPEN hLinePen = NULL, hLinePenErase = NULL, originalPen = NULL;
HDC hdcPctrBox = NULL;

hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
originalPen = SelectObject(hdcPctrBox, GetStockObject(DC_PEN));
//create the two pens

//in the end release resources
SelectObject(hdcPctrBox, originalPen);
DeleteObject(hLinePen);
DeleteObject(hLinePenErase);
ReleaseDC(hwndPctrBox, hdcPctrBox);

瓦尔特



Answer 2:

我建议实现自己的绘画课。 从“面板”或“用户控件”派生自己的类,做在构造函数中,从而激活双缓冲和最优化的绘图以下内容:

public ref class MyPaintControl : public System::Windows::Forms::UserControl
{
public:
    MyPaintControl()
    {
        this->SetStyle(System::Windows::Forms::ControlStyles::AllPaintingInWmPaint, true);
        this->SetStyle(System::Windows::Forms::ControlStyles::DoubleBuffer, true);
        this->SetStyle(System::Windows::Forms::ControlStyles::ResizeRedraw, true);
        this->SetStyle(System::Windows::Forms::ControlStyles::UserPaint, true);
    }

 // And then implement your painting in OnPaint:

protected: 
    virtual void OnPaint(PaintEventArgs^ e)
    {
      // Do painting...
      System::Drawing::Brush^ br = gcnew System::Drawing::SolidBrush(this->BackColor);
      e->Graphics->FillRectangle(br, this->ClientRectangle);
      delete br;

     // Do other paintings...
    }

    // This function might be called if new data arrived...
    public:
      void UpdateArea(int daten)  // pass data here, if you want...
      {
        // Store the data in a member variable...

        // force a redraw:
        this->InvalidateRect(); // this will force a "OnPaint"
      }
}

然后使嵌入在你的UI该控件。 这应该改善你的画非常感谢!

而且这个工程,即使你移动或调整窗口的大小。 要知道,画应始终 “的OnPaint”完成了!



Answer 3:

我想更新我的编码的状态。
我用张贴由Jochen方法。 这是非常快,但它不适合我的应用程序或者也许我不能够适应它。 我需要做的,就是不断更新我的阴谋。 在t0时刻,我要画一条线。 在t1时刻,当我存储新线,我应该吸取新的生产线,这增加了前一个。 情节必须是“活着”。 我试图得到一个面板类和重写OnPaint事件,但我只积清爽如果所有线条都存储和显示。



文章来源: Performance issue while using PictureBox