2011-02-01 6 views
1

sin(x)/ xグラフィックをTimerコンポーネントによってアニメーションモードでPictureBoxに描画する必要があります。私は軸が既に私のpicBoxにあり、グラフィックは0から0を引きます。また、私はこのフォーラムからいくつかのコードを持っていますが、私のグラフィックは左から右に引かれ、左から右に描画する必要があります。アニメーションモードでタイマーで描画する必要があります。誰も私を助けることができますか? 私の描画機能は次のとおりです。TimerコンポーネントによってアニメーションモードでPictureBoxにsin(x)/ xを描画する

private void drawStream() 
    { 
     const int scaleX = 35; 
     const int scaleY = 35; 

     Point picBoxTopLeft = new Point(0, 0); 
     Point picBoxTopLeftm1 = new Point(-1, 0);   

     int halfX = picBox.Width/2; 
     int halfY = picBox.Height/2; 
     Size size = new Size(halfX + 20, picBox.Height); 

     Graphics gr = picBox.CreateGraphics(); 
     gr.TranslateTransform(halfX, halfY); 

     gr.ScaleTransform(scaleX, scaleY); 

     gr.ResetClip(); 

     float lastY = (float)Math.Sin(0); 
     float y = lastY; 
     Pen p = new Pen(Color.Red, 0.015F); 
     float stepX = 1F/scaleX; 

     for (float x = 0; x < 15; x += stepX) 
     { 
      gr.CopyFromScreen(picBox.PointToScreen(picBoxTopLeft), picBoxTopLeftm1, size, CopyPixelOperation.SourceCopy);    
      y = (float)Math.Sin(x); 
      gr.DrawLine(p, -stepX, lastY, 0, y); 
      lastY = y;     
     } 
    } 

Thanxたくさん。 P.P.私の英語で申し訳ありません、私はウクライナ語です。

+0

終了したら、必ず「ペン」を廃棄してください。 'using'ステートメントに入れてください。 –

+0

高尚ですが、私はそれを使用しますペンp =新しいペン(Color.Red、0.015F)。 – Daria

+0

私の答えは私の編集を参照してください。 –

答えて

4

それはラインのようになります。

gr.DrawLine(p, -stepX, lastY, 0, y); 

は常に(0、y)に(-stepX、lastY)から線を引きます。これらのポイントのY座標だけがあなたのループの間に変化し、あなたの望むものとは異なって見えます。

また、X方向にstepXで1/35.0fと定義されています。これは、ピクセル全体で35回ステップしていることを意味します。少し過剰です。あなたのScaleTransformを取り除き、独立した変数(x)をスケールしてより合理的な周波数を得るようにしてください。あなたはまた、よく見えるカーブを得るためにあなたのamplitudeを増やすべきでしょう。

私はあなたの描画ループはより多くのようになるはずだと思う:

for (int x = 1; x < halfX; x += 1) 
{   
    y = (float) amplitude * Math.Sin(x * stepX); 
    gr.DrawLine(p, x - 1, lastY, x, y); 
    lastY = y;     
} 

これは、一度にピクチャボックスの右側に、原点(0,0)から描画されます。これをアニメートするには、このコードを取得する必要があります。halfXにループするのではなく、次回にどこの場所でループするかを把握したい場合は、Timerイベントを発生させます。

編集:

あなたがGDI経由のWindowsからのハンドルを取るPenオブジェクトを作成するたびに。これらのハンドルは、Dispose()Penオブジェクトの場合にのみ返されます。描画するたびに新しいペンを作成して処分しないと、最終的にはハンドルがなくなります!

オブジェクト(PenBrushFont、および配置される、より必要性)のこれらのタイプを使用している場合using声明でそれらをラップし、安全であると:

using (Pen pen = new Pen(Color.Red, 0.015f)) { 
    // ... use the pen here 
} 
// After here it is Disposed and cannot be accessed 
-1

1)右から左へ。 forループを変更してください。

(フロートX = size.Widthため

なる; X> = 0; X(; X < 15×+ = stepXフロートX = 0)のための

- = stepX)

2)タイマー。

単純な解決策は、単に睡眠を追加することです。

for (float x = 0; x < 15; x += stepX) 
Thread.Sleep(500); //draw... 
+0

-1、Thread.SleepはGUIに制御を戻さず、実際にはロックします。 – user7116

+0

ありがとうございますが、私はTIMERを使う労力があります。奇妙だが何も変わっていない、私のグラフィックはまだ左から右に描かれている。 – Daria

+1

はい、スリープを使用するとメインスレッドがブロックされます。タイマーを使用して修正する必要があります。 – Carra

2

いいえ、自分で試してみるのに20分かかりました。

public Form1() 
{ 
    InitializeComponent(); 

    _bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height); 
    pictureBox1.Image = _bitmap; 

    Timer timer = new Timer(); 
    timer.Tick += new EventHandler(timer_Tick); 
    timer.Interval = 10; 

    timer.Start(); 
} 

private int x = 0; 
void timer_Tick(object sender, EventArgs e) 
{ 
    if(++x < _bitmap.Width) 
    { 
     int y = _bitmap.Height/2 
       - ((int)(Math.Sin(x * (Math.PI * 2)/_bitmap.Width) * (_bitmap.Height/2))); 

     //Small rounding error 
     if (y > _bitmap.Height - 1) 
      y = _bitmap.Height - 1; 

     _bitmap.SetPixel(x, y, Color.Black); 
    } 
    pictureBox1.Image = _bitmap; 
} 

テスト済みです。

0

実際にはGraphicsPathにポイントを追加し、それをペイントするだけです。

また、次のようなGraphicsオブジェクトを作成しないでください。 Bitmapから1つを取得するか、Paintイベントで提供されているものを使用してください。

関連する問題