使用PictureBox时的性能问题 [英] Performance issue while using PictureBox
问题描述
我在Visual Studio 2010中编写一个应用程序,我在C ++ / CLI中编码。
在我以前的问题中,我遇到了来自串行端口的数据系列问题。现在它似乎确定,现在我试图绘制它们。
我不想使用图表
,所以我想使用手工制作使用类 Graphics
的函数。为了测试我的代码,我创建了两个数组:第一个数组填充了来自高斯的值。第二个用随机数填充。
当我绘制值时,我想看到我的情节正在增长和更新,就像示波器。第二个 Do_Plot
设法通过BackColor绘制它们的删除点。
所有的代码工作原理,但我遇到问题的性能。如果我在我的PC上运行代码,我的系列是每500/700毫秒绘制。
有时它会减慢到1500毫秒,然后它回来更快。
我试图运行我的同事Pc和我注意到系列是每170ms绘制在第一个,而系列绘制每950ms在第二个。
这是代码:
I'm working on an application in Visual Studio 2010 and I'm coding in C++/CLI.
In my previous questions I had issue with data series from a serial port. Now it seems ok and now I'm trying to plot them.
I don't want to use Chart
, so I would like to use handmade functions that use the class Graphics
. In order to test my code, I created two arrays: the first one is filled with values coming from a Gaussian. The second one is filled with random numbers.
When I plot the values, I would like to see my plot growing and updating just like an oscilloscope. The second Do_Plot
manages to "remove point" plotting them by the BackColor.
All the code works as intended but I'm experiencing problem with performances. If I run the code on my Pc, my series is plotted every 500/700 ms.
Sometimes it slows down to 1500ms and then it comes back faster.
I tried to run the code on my coworkers' Pc and I noticed the series is plotted every 170ms on the first one, whereas the series is plotted every 950ms on the second one.
This is the code:
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();
}
至少我不知道为什么我的代码工作如此不同当它运行在另一个Pc。我认为问题是 g = pictureBox1-> CreateGraphics();
但我只是做一些假设。任何种类的帮助将真正感谢因为我从上一周卡在这一个!
非常感谢
Emiliano
Onestly I don't know why my code works so differently when it runs on another Pc. I think the problem is g = pictureBox1->CreateGraphics();
but I'm just doing some hypothesis. Any kind of help would be really appreciated cause I'm stuck on this one since the previous week!!
Thanks a lot!
Emiliano
推荐答案
我将给你c / c ++中的代码。然后将在c ++ / cli中找到如何做它
I am going to give you the code in c/c++. Will then find how to do it in c++/cli
首先初始化我们将使用的对象(button_click的开始):
First initialize the objects we will use (begining of 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
最后我们绘制它,在for循环之后,clock_t Stop (我们不需要Do_Plot()):
And finaly we draw it, after the for loop and before the clock_t Stop (we dont need the Do_Plot()):
Polyline(hdcMemTempImage, &arrayPnt, 1000);
BitBlt(hdcPctrBox, 0, 0, 1200, 600, hdcMemTempImage, 0, 0, SRCCOPY);
clock_t Stop = clock();
//your code continues...
编辑:使用您的原始代码>您不需要 Do_Plot()
添加此代码,而不需要 rt,hBitmap,hBrush,hdcMemTempImage,arrayPnt和hdc :
use your original code(you dont need rt, hBitmap, hBrush, hdcMemTempImage, arrayPnt and hdc) and instead of calling Do_Plot()
add this code:
//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);
valter
这篇关于使用PictureBox时的性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!